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.
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 Fri Jul 15 2022 01:46:33 by
1.7.2