fork
Fork of cpputest by
Embed:
(wiki syntax)
Show/hide line numbers
SimpleString.cpp
00001 /* 00002 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the <organization> nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY 00017 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "CppUTest/TestHarness.h" 00029 #include "CppUTest/SimpleString.h" 00030 #include "CppUTest/PlatformSpecificFunctions.h" 00031 #include "CppUTest/TestMemoryAllocator.h" 00032 00033 00034 TestMemoryAllocator* SimpleString::stringAllocator_ = NULL; 00035 00036 TestMemoryAllocator* SimpleString::getStringAllocator() 00037 { 00038 if (stringAllocator_ == NULL) 00039 return defaultNewArrayAllocator(); 00040 return stringAllocator_; 00041 } 00042 00043 void SimpleString::setStringAllocator(TestMemoryAllocator* allocator) 00044 { 00045 stringAllocator_ = allocator; 00046 } 00047 00048 /* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */ 00049 char* SimpleString::allocStringBuffer(size_t _size) 00050 { 00051 return getStringAllocator()->alloc_memory(_size, __FILE__, __LINE__); 00052 } 00053 00054 void SimpleString::deallocStringBuffer(char* str) 00055 { 00056 getStringAllocator()->free_memory(str, __FILE__, __LINE__); 00057 } 00058 00059 char* SimpleString::getEmptyString() const 00060 { 00061 char* empty = allocStringBuffer(1); 00062 empty[0] = '\0'; 00063 return empty; 00064 } 00065 00066 char* SimpleString::StrNCpy(char* s1, const char* s2, size_t n) 00067 { 00068 char* result = s1; 00069 00070 if((NULL == s1) || (0 == n)) return result; 00071 00072 while ((*s1++ = *s2++) && --n != 0) 00073 ; 00074 return result; 00075 } 00076 00077 SimpleString::SimpleString(const char *otherBuffer) 00078 { 00079 if (otherBuffer == 0) { 00080 buffer_ = getEmptyString(); 00081 } 00082 else { 00083 buffer_ = copyToNewBuffer(otherBuffer); 00084 } 00085 } 00086 00087 SimpleString::SimpleString(const char *other, size_t repeatCount) 00088 { 00089 size_t otherStringLength = PlatformSpecificStrLen(other); 00090 size_t len = otherStringLength * repeatCount + 1; 00091 buffer_ = allocStringBuffer(len); 00092 char* next = buffer_; 00093 for (size_t i = 0; i < repeatCount; i++) { 00094 StrNCpy(next, other, otherStringLength + 1); 00095 next += otherStringLength; 00096 } 00097 *next = 0; 00098 } 00099 00100 SimpleString::SimpleString(const SimpleString& other) 00101 { 00102 buffer_ = copyToNewBuffer(other.buffer_); 00103 } 00104 00105 SimpleString& SimpleString::operator=(const SimpleString& other) 00106 { 00107 if (this != &other) { 00108 deallocStringBuffer(buffer_); 00109 buffer_ = copyToNewBuffer(other.buffer_); 00110 } 00111 return *this; 00112 } 00113 00114 bool SimpleString::contains(const SimpleString& other) const 00115 { 00116 //strstr on some machines does not handle "" 00117 //the right way. "" should be found in any string 00118 if (PlatformSpecificStrLen(other.buffer_) == 0) return true; 00119 else if (PlatformSpecificStrLen(buffer_) == 0) return false; 00120 else return PlatformSpecificStrStr(buffer_, other.buffer_) != 0; 00121 } 00122 00123 bool SimpleString::containsNoCase(const SimpleString& other) const 00124 { 00125 return toLower().contains(other.toLower()); 00126 } 00127 00128 00129 bool SimpleString::startsWith(const SimpleString& other) const 00130 { 00131 if (PlatformSpecificStrLen(other.buffer_) == 0) return true; 00132 else if (PlatformSpecificStrLen(buffer_) == 0) return false; 00133 else return PlatformSpecificStrStr(buffer_, other.buffer_) == buffer_; 00134 } 00135 00136 bool SimpleString::endsWith(const SimpleString& other) const 00137 { 00138 size_t buffer_length = PlatformSpecificStrLen(buffer_); 00139 size_t other_buffer_length = PlatformSpecificStrLen(other.buffer_); 00140 if (other_buffer_length == 0) return true; 00141 if (buffer_length == 0) return false; 00142 if (buffer_length < other_buffer_length) return false; 00143 return PlatformSpecificStrCmp(buffer_ + buffer_length - other_buffer_length, other.buffer_) == 0; 00144 } 00145 00146 size_t SimpleString::count(const SimpleString& substr) const 00147 { 00148 size_t num = 0; 00149 char* str = buffer_; 00150 while ((str = PlatformSpecificStrStr(str, substr.buffer_))) { 00151 num++; 00152 str++; 00153 } 00154 return num; 00155 } 00156 00157 void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection& col) const 00158 { 00159 size_t num = count(delimiter); 00160 size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U; 00161 col.allocate(num + extraEndToken); 00162 00163 char* str = buffer_; 00164 char* prev; 00165 for (size_t i = 0; i < num; ++i) { 00166 prev = str; 00167 str = PlatformSpecificStrStr(str, delimiter.buffer_) + 1; 00168 size_t len = (size_t) (str - prev) + 1; 00169 col[i].buffer_ = copyToNewBuffer(prev, len); 00170 } 00171 if (extraEndToken) { 00172 col[num] = str; 00173 } 00174 } 00175 00176 void SimpleString::replace(char to, char with) 00177 { 00178 size_t s = size(); 00179 for (size_t i = 0; i < s; i++) { 00180 if (buffer_[i] == to) buffer_[i] = with; 00181 } 00182 } 00183 00184 void SimpleString::replace(const char* to, const char* with) 00185 { 00186 size_t c = count(to); 00187 size_t len = size(); 00188 size_t tolen = PlatformSpecificStrLen(to); 00189 size_t withlen = PlatformSpecificStrLen(with); 00190 00191 size_t newsize = len + (withlen * c) - (tolen * c) + 1; 00192 00193 if (newsize) { 00194 char* newbuf = allocStringBuffer(newsize); 00195 for (size_t i = 0, j = 0; i < len;) { 00196 if (PlatformSpecificStrNCmp(&buffer_[i], to, tolen) == 0) { 00197 StrNCpy(&newbuf[j], with, withlen + 1); 00198 j += withlen; 00199 i += tolen; 00200 } 00201 else { 00202 newbuf[j] = buffer_[i]; 00203 j++; 00204 i++; 00205 } 00206 } 00207 deallocStringBuffer(buffer_); 00208 buffer_ = newbuf; 00209 buffer_[newsize - 1] = '\0'; 00210 } 00211 else { 00212 buffer_ = getEmptyString(); 00213 buffer_[0] = '\0'; 00214 } 00215 } 00216 00217 SimpleString SimpleString::toLower() const 00218 { 00219 SimpleString str(*this); 00220 00221 size_t str_size = str.size(); 00222 for (size_t i = 0; i < str_size; i++) 00223 str.buffer_[i] = PlatformSpecificToLower(str.buffer_[i]); 00224 00225 return str; 00226 } 00227 00228 const char *SimpleString::asCharString() const 00229 { 00230 return buffer_; 00231 } 00232 00233 size_t SimpleString::size() const 00234 { 00235 return PlatformSpecificStrLen(buffer_); 00236 } 00237 00238 bool SimpleString::isEmpty() const 00239 { 00240 return size() == 0; 00241 } 00242 00243 00244 00245 SimpleString::~SimpleString() 00246 { 00247 deallocStringBuffer(buffer_); 00248 } 00249 00250 bool operator==(const SimpleString& left, const SimpleString& right) 00251 { 00252 return 0 == PlatformSpecificStrCmp(left.asCharString(), right.asCharString()); 00253 } 00254 00255 bool SimpleString::equalsNoCase(const SimpleString& str) const 00256 { 00257 return toLower() == str.toLower(); 00258 } 00259 00260 00261 bool operator!=(const SimpleString& left, const SimpleString& right) 00262 { 00263 return !(left == right); 00264 } 00265 00266 SimpleString SimpleString::operator+(const SimpleString& rhs) 00267 { 00268 SimpleString t(buffer_); 00269 t += rhs.buffer_; 00270 return t; 00271 } 00272 00273 SimpleString& SimpleString::operator+=(const SimpleString& rhs) 00274 { 00275 return operator+=(rhs.buffer_); 00276 } 00277 00278 SimpleString& SimpleString::operator+=(const char* rhs) 00279 { 00280 size_t originalSize = this->size(); 00281 size_t additionalStringSize = PlatformSpecificStrLen(rhs) + 1; 00282 size_t sizeOfNewString = originalSize + additionalStringSize; 00283 char* tbuffer = copyToNewBuffer(this->buffer_, sizeOfNewString); 00284 StrNCpy(tbuffer + originalSize, rhs, additionalStringSize); 00285 deallocStringBuffer(this->buffer_); 00286 this->buffer_ = tbuffer; 00287 return *this; 00288 } 00289 00290 void SimpleString::padStringsToSameLength(SimpleString& str1, SimpleString& str2, char padCharacter) 00291 { 00292 if (str1.size() > str2.size()) { 00293 padStringsToSameLength(str2, str1, padCharacter); 00294 return; 00295 } 00296 00297 char pad[2]; 00298 pad[0] = padCharacter; 00299 pad[1] = 0; 00300 str1 = SimpleString(pad, str2.size() - str1.size()) + str1; 00301 } 00302 00303 SimpleString SimpleString::subString(size_t beginPos, size_t amount) const 00304 { 00305 if (beginPos > size()-1) return ""; 00306 00307 SimpleString newString = buffer_ + beginPos; 00308 00309 if (newString.size() > amount) 00310 newString.buffer_[amount] = '\0'; 00311 00312 return newString; 00313 } 00314 00315 char SimpleString::at(int pos) const 00316 { 00317 return buffer_[pos]; 00318 } 00319 00320 int SimpleString::find(char ch) const 00321 { 00322 return findFrom(0, ch); 00323 } 00324 00325 int SimpleString::findFrom(size_t starting_position, char ch) const 00326 { 00327 size_t length = size(); 00328 for (size_t i = starting_position; i < length; i++) 00329 if (buffer_[i] == ch) return (int) i; 00330 return -1; 00331 } 00332 00333 SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedChar) const 00334 { 00335 int beginPos = find(startChar); 00336 if (beginPos < 0) return ""; 00337 00338 int endPos = findFrom((size_t)beginPos, lastExcludedChar); 00339 if (endPos == -1) return subString((size_t)beginPos, size()); 00340 00341 return subString((size_t)beginPos, (size_t) (endPos - beginPos)); 00342 } 00343 00344 char* SimpleString::copyToNewBuffer(const char* bufferToCopy, size_t bufferSize) 00345 { 00346 if(bufferSize == 0) bufferSize = PlatformSpecificStrLen(bufferToCopy) + 1; 00347 00348 char* newBuffer = allocStringBuffer(bufferSize); 00349 StrNCpy(newBuffer, bufferToCopy, bufferSize); 00350 newBuffer[bufferSize-1] = '\0'; 00351 return newBuffer; 00352 } 00353 00354 void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const 00355 { 00356 if (bufferToCopy == NULL || bufferSize == 0) return; 00357 00358 size_t sizeToCopy = (bufferSize-1 < size()) ? bufferSize : size(); 00359 00360 StrNCpy(bufferToCopy, buffer_, sizeToCopy); 00361 bufferToCopy[sizeToCopy] = '\0'; 00362 } 00363 00364 SimpleString StringFrom(bool value) 00365 { 00366 return SimpleString(StringFromFormat("%s", value ? "true" : "false")); 00367 } 00368 00369 SimpleString StringFrom(const char *value) 00370 { 00371 return SimpleString(value); 00372 } 00373 00374 SimpleString StringFromOrNull(const char * expected) 00375 { 00376 return (expected) ? StringFrom(expected) : "(null)"; 00377 } 00378 00379 SimpleString StringFrom(int value) 00380 { 00381 return StringFromFormat("%d", value); 00382 } 00383 00384 SimpleString StringFrom(long value) 00385 { 00386 return StringFromFormat("%ld", value); 00387 } 00388 00389 SimpleString StringFrom(const void* value) 00390 { 00391 return SimpleString("0x") + HexStringFrom(value); 00392 } 00393 00394 SimpleString HexStringFrom(long value) 00395 { 00396 return StringFromFormat("%lx", value); 00397 } 00398 00399 SimpleString HexStringFrom(unsigned long value) 00400 { 00401 return StringFromFormat("%lx", value); 00402 } 00403 00404 static long convertPointerToLongValue(const void* value) 00405 { 00406 /* 00407 * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating. 00408 * This isn't the right way to convert pointers values and need to change by implementing a 00409 * proper portable way to convert pointers to strings. 00410 */ 00411 long* long_value = (long*) &value; 00412 return *long_value; 00413 } 00414 00415 SimpleString HexStringFrom(const void* value) 00416 { 00417 return StringFromFormat("%lx", convertPointerToLongValue(value)); 00418 } 00419 00420 SimpleString StringFrom(double value, int precision) 00421 { 00422 return StringFromFormat("%.*g", precision, value); 00423 } 00424 00425 SimpleString StringFrom(char value) 00426 { 00427 return StringFromFormat("%c", value); 00428 } 00429 00430 SimpleString StringFrom(const SimpleString& value) 00431 { 00432 return SimpleString(value); 00433 } 00434 00435 SimpleString StringFromFormat(const char* format, ...) 00436 { 00437 SimpleString resultString; 00438 va_list arguments; 00439 va_start(arguments, format); 00440 00441 resultString = VStringFromFormat(format, arguments); 00442 va_end(arguments); 00443 return resultString; 00444 } 00445 00446 SimpleString StringFrom(unsigned int i) 00447 { 00448 return StringFromFormat("%10u (0x%08x)", i, i); 00449 } 00450 00451 #if CPPUTEST_USE_STD_CPP_LIB 00452 00453 #include <string> 00454 00455 SimpleString StringFrom(const std::string& value) 00456 { 00457 return SimpleString(value.c_str()); 00458 } 00459 00460 SimpleString StringFrom(unsigned long i) 00461 { 00462 return StringFromFormat("%lu (0x%lx)", i, i); 00463 } 00464 00465 #else 00466 00467 SimpleString StringFrom(unsigned long value) 00468 { 00469 return StringFromFormat("%lu", value); 00470 } 00471 00472 #endif 00473 00474 //Kludge to get a va_copy in VC++ V6 00475 #ifndef va_copy 00476 #define va_copy(copy, original) copy = original; 00477 #endif 00478 00479 SimpleString VStringFromFormat(const char* format, va_list args) 00480 { 00481 va_list argsCopy; 00482 va_copy(argsCopy, args); 00483 enum 00484 { 00485 sizeOfdefaultBuffer = 100 00486 }; 00487 char defaultBuffer[sizeOfdefaultBuffer]; 00488 SimpleString resultString; 00489 00490 size_t size = (size_t)PlatformSpecificVSNprintf(defaultBuffer, sizeOfdefaultBuffer, format, args); 00491 if (size < sizeOfdefaultBuffer) { 00492 resultString = SimpleString(defaultBuffer); 00493 } 00494 else { 00495 size_t newBufferSize = size + 1; 00496 char* newBuffer = SimpleString::allocStringBuffer(newBufferSize); 00497 PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy); 00498 resultString = SimpleString(newBuffer); 00499 00500 SimpleString::deallocStringBuffer(newBuffer); 00501 } 00502 va_end(argsCopy); 00503 return resultString; 00504 } 00505 00506 SimpleStringCollection::SimpleStringCollection() 00507 { 00508 collection_ = 0; 00509 size_ = 0; 00510 } 00511 00512 void SimpleStringCollection::allocate(size_t _size) 00513 { 00514 delete[] collection_; 00515 00516 size_ = _size; 00517 collection_ = new SimpleString[size_]; 00518 } 00519 00520 SimpleStringCollection::~SimpleStringCollection() 00521 { 00522 delete[] (collection_); 00523 } 00524 00525 size_t SimpleStringCollection::size() const 00526 { 00527 return size_; 00528 } 00529 00530 SimpleString& SimpleStringCollection::operator[](size_t index) 00531 { 00532 if (index >= size_) { 00533 empty_ = ""; 00534 return empty_; 00535 } 00536 00537 return collection_[index]; 00538 }
Generated on Tue Jul 12 2022 21:37:56 by 1.7.2