1 /*
2  * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the <organization> nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "CppUTest/TestHarness.h"
29 #include "CppUTest/SimpleString.h"
30 #include "CppUTest/PlatformSpecificFunctions.h"
31 #include "CppUTest/TestMemoryAllocator.h"
32 
GlobalSimpleStringAllocatorStash()33 GlobalSimpleStringAllocatorStash::GlobalSimpleStringAllocatorStash()
34     : originalAllocator_(NULLPTR)
35 {
36 }
37 
save()38 void GlobalSimpleStringAllocatorStash::save()
39 {
40     originalAllocator_ = SimpleString::getStringAllocator();
41 }
42 
restore()43 void GlobalSimpleStringAllocatorStash::restore()
44 {
45     SimpleString::setStringAllocator(originalAllocator_);
46 }
47 
48 
GlobalSimpleStringMemoryAccountant()49 GlobalSimpleStringMemoryAccountant::GlobalSimpleStringMemoryAccountant()
50     : allocator_(NULLPTR)
51 {
52     accountant_ = new MemoryAccountant();
53 }
54 
~GlobalSimpleStringMemoryAccountant()55 GlobalSimpleStringMemoryAccountant::~GlobalSimpleStringMemoryAccountant()
56 {
57     restoreAllocator();
58 
59     delete accountant_;
60     delete allocator_;
61 }
62 
restoreAllocator()63 void GlobalSimpleStringMemoryAccountant::restoreAllocator()
64 {
65     if (SimpleString::getStringAllocator() == allocator_)
66         SimpleString::setStringAllocator(allocator_->originalAllocator());
67 }
68 
useCacheSizes(size_t cacheSizes[],size_t length)69 void GlobalSimpleStringMemoryAccountant::useCacheSizes(size_t cacheSizes[], size_t length)
70 {
71     accountant_->useCacheSizes(cacheSizes, length);
72 }
73 
start()74 void GlobalSimpleStringMemoryAccountant::start()
75 {
76     if (allocator_ != NULLPTR)
77       return;
78 
79     allocator_ = new AccountingTestMemoryAllocator(*accountant_, SimpleString::getStringAllocator());
80 
81     SimpleString::setStringAllocator(allocator_);
82 }
83 
stop()84 void GlobalSimpleStringMemoryAccountant::stop()
85 {
86     if (allocator_ == NULLPTR)
87         FAIL("Global SimpleString allocator stopped without starting");
88 
89     if (SimpleString::getStringAllocator() != allocator_)
90       FAIL("GlobalStrimpleStringMemoryAccountant: allocator has changed between start and stop!");
91 
92     restoreAllocator();
93 }
94 
report()95 SimpleString GlobalSimpleStringMemoryAccountant::report()
96 {
97     return accountant_->report();
98 }
99 
getAllocator()100 AccountingTestMemoryAllocator* GlobalSimpleStringMemoryAccountant::getAllocator()
101 {
102     return allocator_;
103 }
104 
105 TestMemoryAllocator* SimpleString::stringAllocator_ = NULLPTR;
106 
getStringAllocator()107 TestMemoryAllocator* SimpleString::getStringAllocator()
108 {
109     if (stringAllocator_ == NULLPTR)
110         return defaultNewArrayAllocator();
111     return stringAllocator_;
112 }
113 
setStringAllocator(TestMemoryAllocator * allocator)114 void SimpleString::setStringAllocator(TestMemoryAllocator* allocator)
115 {
116     stringAllocator_ = allocator;
117 }
118 
119 /* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */
allocStringBuffer(size_t _size,const char * file,size_t line)120 char* SimpleString::allocStringBuffer(size_t _size, const char* file, size_t line)
121 {
122     return getStringAllocator()->alloc_memory(_size, file, line);
123 }
124 
deallocStringBuffer(char * str,size_t size,const char * file,size_t line)125 void SimpleString::deallocStringBuffer(char* str, size_t size, const char* file, size_t line)
126 {
127     getStringAllocator()->free_memory(str, size, file, line);
128 }
129 
getEmptyString() const130 char* SimpleString::getEmptyString() const
131 {
132     char* empty = allocStringBuffer(1, __FILE__, __LINE__);
133     empty[0] = '\0';
134     return empty;
135 }
136 
137 // does not support + or - prefixes
AtoU(const char * str)138 unsigned SimpleString::AtoU(const char* str)
139 {
140     while (isSpace(*str)) str++;
141 
142     unsigned result = 0;
143     for(; isDigit(*str) && *str >= '0'; str++)
144     {
145         result *= 10;
146         result += static_cast<unsigned>(*str - '0');
147     }
148     return result;
149 }
150 
AtoI(const char * str)151 int SimpleString::AtoI(const char* str)
152 {
153     while (isSpace(*str)) str++;
154 
155     char first_char = *str;
156     if (first_char == '-' || first_char == '+') str++;
157 
158     int  result = 0;
159     for(; isDigit(*str); str++)
160     {
161         result *= 10;
162         result += *str - '0';
163     }
164     return (first_char == '-') ? -result : result;
165 }
166 
StrCmp(const char * s1,const char * s2)167 int SimpleString::StrCmp(const char* s1, const char* s2)
168 {
169    while(*s1 && *s1 == *s2) {
170        ++s1;
171        ++s2;
172    }
173    return *(const unsigned char *) s1 - *(const unsigned char *) s2;
174 }
175 
StrLen(const char * str)176 size_t SimpleString::StrLen(const char* str)
177 {
178     size_t n = (size_t)-1;
179     do n++; while (*str++);
180     return n;
181 }
182 
StrNCmp(const char * s1,const char * s2,size_t n)183 int SimpleString::StrNCmp(const char* s1, const char* s2, size_t n)
184 {
185     while (n && *s1 && *s1 == *s2) {
186         --n;
187         ++s1;
188         ++s2;
189     }
190     return n ? *(const unsigned char *) s1 - *(const unsigned char *) s2 : 0;
191 }
192 
StrNCpy(char * s1,const char * s2,size_t n)193 char* SimpleString::StrNCpy(char* s1, const char* s2, size_t n)
194 {
195     char* result = s1;
196 
197     if((NULLPTR == s1) || (0 == n)) return result;
198 
199     while ((*s1++ = *s2++) && --n != 0)
200         ;
201     return result;
202 }
203 
StrStr(const char * s1,const char * s2)204 const char* SimpleString::StrStr(const char* s1, const char* s2)
205 {
206     if(!*s2) return s1;
207     for (; *s1; s1++)
208         if (StrNCmp(s1, s2, StrLen(s2)) == 0)
209             return s1;
210     return NULLPTR;
211 }
212 
ToLower(char ch)213 char SimpleString::ToLower(char ch)
214 {
215     return isUpper(ch) ? (char)((int)ch + ('a' - 'A')) : ch;
216 }
217 
MemCmp(const void * s1,const void * s2,size_t n)218 int SimpleString::MemCmp(const void* s1, const void *s2, size_t n)
219 {
220     const unsigned char* p1 = (const unsigned char*) s1;
221     const unsigned char* p2 = (const unsigned char*) s2;
222 
223     while (n--)
224         if (*p1 != *p2) {
225             return *p1 - *p2;
226         } else {
227             ++p1;
228             ++p2;
229         }
230     return 0;
231 }
232 
deallocateInternalBuffer()233 void SimpleString::deallocateInternalBuffer()
234 {
235     if (buffer_) {
236         deallocStringBuffer(buffer_, bufferSize_, __FILE__, __LINE__);
237         buffer_ = NULLPTR;
238         bufferSize_ = 0;
239     }
240 }
241 
setInternalBufferAsEmptyString()242 void SimpleString::setInternalBufferAsEmptyString()
243 {
244     deallocateInternalBuffer();
245 
246     bufferSize_ = 1;
247     buffer_ = getEmptyString();
248 }
249 
copyBufferToNewInternalBuffer(const char * otherBuffer,size_t bufferSize)250 void SimpleString::copyBufferToNewInternalBuffer(const char* otherBuffer, size_t bufferSize)
251 {
252     deallocateInternalBuffer();
253 
254     bufferSize_ = bufferSize;
255     buffer_ = copyToNewBuffer(otherBuffer, bufferSize_);
256 }
257 
setInternalBufferToNewBuffer(size_t bufferSize)258 void SimpleString::setInternalBufferToNewBuffer(size_t bufferSize)
259 {
260     deallocateInternalBuffer();
261 
262     bufferSize_ = bufferSize;
263     buffer_ = allocStringBuffer(bufferSize_, __FILE__, __LINE__);
264     buffer_[0] = '\0';
265 }
266 
setInternalBufferTo(char * buffer,size_t bufferSize)267 void SimpleString::setInternalBufferTo(char* buffer, size_t bufferSize)
268 {
269     deallocateInternalBuffer();
270 
271     bufferSize_ = bufferSize;
272     buffer_ = buffer;
273 }
274 
copyBufferToNewInternalBuffer(const SimpleString & otherBuffer)275 void SimpleString::copyBufferToNewInternalBuffer(const SimpleString& otherBuffer)
276 {
277     copyBufferToNewInternalBuffer(otherBuffer.buffer_, otherBuffer.size() + 1);
278 }
279 
copyBufferToNewInternalBuffer(const char * otherBuffer)280 void SimpleString::copyBufferToNewInternalBuffer(const char* otherBuffer)
281 {
282     copyBufferToNewInternalBuffer(otherBuffer, StrLen(otherBuffer) + 1);
283 }
284 
getBuffer() const285 const char* SimpleString::getBuffer() const
286 {
287     return buffer_;
288 }
289 
SimpleString(const char * otherBuffer)290 SimpleString::SimpleString(const char *otherBuffer)
291     : buffer_(NULLPTR), bufferSize_(0)
292 {
293     if (otherBuffer == NULLPTR)
294         setInternalBufferAsEmptyString();
295     else
296         copyBufferToNewInternalBuffer(otherBuffer);
297 }
298 
SimpleString(const char * other,size_t repeatCount)299 SimpleString::SimpleString(const char *other, size_t repeatCount)
300     : buffer_(NULLPTR), bufferSize_(0)
301 {
302     size_t otherStringLength = StrLen(other);
303     setInternalBufferToNewBuffer(otherStringLength * repeatCount + 1);
304 
305     char* next = buffer_;
306     for (size_t i = 0; i < repeatCount; i++) {
307         StrNCpy(next, other, otherStringLength + 1);
308         next += otherStringLength;
309     }
310     *next = 0;
311 }
312 
SimpleString(const SimpleString & other)313 SimpleString::SimpleString(const SimpleString& other)
314     : buffer_(NULLPTR), bufferSize_(0)
315 {
316     copyBufferToNewInternalBuffer(other.getBuffer());
317 }
318 
operator =(const SimpleString & other)319 SimpleString& SimpleString::operator=(const SimpleString& other)
320 {
321     if (this != &other)
322         copyBufferToNewInternalBuffer(other);
323     return *this;
324 }
325 
contains(const SimpleString & other) const326 bool SimpleString::contains(const SimpleString& other) const
327 {
328     return StrStr(getBuffer(), other.getBuffer()) != NULLPTR;
329 }
330 
containsNoCase(const SimpleString & other) const331 bool SimpleString::containsNoCase(const SimpleString& other) const
332 {
333     return lowerCase().contains(other.lowerCase());
334 }
335 
startsWith(const SimpleString & other) const336 bool SimpleString::startsWith(const SimpleString& other) const
337 {
338     if (other.size() == 0) return true;
339     else if (size() == 0) return false;
340     else return StrStr(getBuffer(), other.getBuffer()) == getBuffer();
341 }
342 
endsWith(const SimpleString & other) const343 bool SimpleString::endsWith(const SimpleString& other) const
344 {
345     size_t length = size();
346     size_t other_length = other.size();
347 
348     if (other_length == 0) return true;
349     if (length == 0) return false;
350     if (length < other_length) return false;
351 
352     return StrCmp(getBuffer() + length - other_length, other.getBuffer()) == 0;
353 }
354 
count(const SimpleString & substr) const355 size_t SimpleString::count(const SimpleString& substr) const
356 {
357     size_t num = 0;
358     const char* str = getBuffer();
359     while (*str && (str = StrStr(str, substr.getBuffer()))) {
360         str++;
361         num++;
362     }
363     return num;
364 }
365 
split(const SimpleString & delimiter,SimpleStringCollection & col) const366 void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection& col) const
367 {
368     size_t num = count(delimiter);
369     size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U;
370     col.allocate(num + extraEndToken);
371 
372     const char* str = getBuffer();
373     const char* prev;
374     for (size_t i = 0; i < num; ++i) {
375         prev = str;
376         str = StrStr(str, delimiter.getBuffer()) + 1;
377         col[i] = SimpleString(prev).subString(0, size_t (str - prev));
378     }
379     if (extraEndToken) {
380         col[num] = str;
381     }
382 }
383 
replace(char to,char with)384 void SimpleString::replace(char to, char with)
385 {
386     size_t s = size();
387     for (size_t i = 0; i < s; i++) {
388         if (getBuffer()[i] == to) buffer_[i] = with;
389     }
390 }
391 
replace(const char * to,const char * with)392 void SimpleString::replace(const char* to, const char* with)
393 {
394     size_t c = count(to);
395     if (c == 0) {
396         return;
397     }
398     size_t len = size();
399     size_t tolen = StrLen(to);
400     size_t withlen = StrLen(with);
401 
402     size_t newsize = len + (withlen * c) - (tolen * c) + 1;
403 
404     if (newsize > 1) {
405         char* newbuf = allocStringBuffer(newsize, __FILE__, __LINE__);
406         for (size_t i = 0, j = 0; i < len;) {
407             if (StrNCmp(&getBuffer()[i], to, tolen) == 0) {
408                 StrNCpy(&newbuf[j], with, withlen + 1);
409                 j += withlen;
410                 i += tolen;
411             }
412             else {
413                 newbuf[j] = getBuffer()[i];
414                 j++;
415                 i++;
416             }
417         }
418         newbuf[newsize - 1] = '\0';
419         setInternalBufferTo(newbuf, newsize);
420     }
421     else
422         setInternalBufferAsEmptyString();
423 }
424 
lowerCase() const425 SimpleString SimpleString::lowerCase() const
426 {
427     SimpleString str(*this);
428 
429     size_t str_size = str.size();
430     for (size_t i = 0; i < str_size; i++)
431         str.buffer_[i] = ToLower(str.getBuffer()[i]);
432 
433     return str;
434 }
435 
asCharString() const436 const char *SimpleString::asCharString() const
437 {
438     return getBuffer();
439 }
440 
size() const441 size_t SimpleString::size() const
442 {
443     return StrLen(getBuffer());
444 }
445 
isEmpty() const446 bool SimpleString::isEmpty() const
447 {
448     return size() == 0;
449 }
450 
~SimpleString()451 SimpleString::~SimpleString()
452 {
453     deallocateInternalBuffer();
454 }
455 
operator ==(const SimpleString & left,const SimpleString & right)456 bool operator==(const SimpleString& left, const SimpleString& right)
457 {
458     return 0 == SimpleString::StrCmp(left.asCharString(), right.asCharString());
459 }
460 
equalsNoCase(const SimpleString & str) const461 bool SimpleString::equalsNoCase(const SimpleString& str) const
462 {
463     return lowerCase() == str.lowerCase();
464 }
465 
466 
operator !=(const SimpleString & left,const SimpleString & right)467 bool operator!=(const SimpleString& left, const SimpleString& right)
468 {
469     return !(left == right);
470 }
471 
operator +(const SimpleString & rhs) const472 SimpleString SimpleString::operator+(const SimpleString& rhs) const
473 {
474     SimpleString t(getBuffer());
475     t += rhs.getBuffer();
476     return t;
477 }
478 
operator +=(const SimpleString & rhs)479 SimpleString& SimpleString::operator+=(const SimpleString& rhs)
480 {
481     return operator+=(rhs.getBuffer());
482 }
483 
operator +=(const char * rhs)484 SimpleString& SimpleString::operator+=(const char* rhs)
485 {
486     size_t originalSize = this->size();
487     size_t additionalStringSize = StrLen(rhs) + 1;
488     size_t sizeOfNewString = originalSize + additionalStringSize;
489     char* tbuffer = copyToNewBuffer(this->getBuffer(), sizeOfNewString);
490     StrNCpy(tbuffer + originalSize, rhs, additionalStringSize);
491 
492     setInternalBufferTo(tbuffer, sizeOfNewString);
493     return *this;
494 }
495 
padStringsToSameLength(SimpleString & str1,SimpleString & str2,char padCharacter)496 void SimpleString::padStringsToSameLength(SimpleString& str1, SimpleString& str2, char padCharacter)
497 {
498     if (str1.size() > str2.size()) {
499         padStringsToSameLength(str2, str1, padCharacter);
500         return;
501     }
502 
503     char pad[2];
504     pad[0] = padCharacter;
505     pad[1] = 0;
506     str1 = SimpleString(pad, str2.size() - str1.size()) + str1;
507 }
508 
subString(size_t beginPos,size_t amount) const509 SimpleString SimpleString::subString(size_t beginPos, size_t amount) const
510 {
511     if (beginPos > size()-1) return "";
512 
513     SimpleString newString = getBuffer() + beginPos;
514 
515     if (newString.size() > amount)
516         newString.buffer_[amount] = '\0';
517 
518     return newString;
519 }
520 
subString(size_t beginPos) const521 SimpleString SimpleString::subString(size_t beginPos) const
522 {
523     return subString(beginPos, npos);
524 }
525 
at(size_t pos) const526 char SimpleString::at(size_t pos) const
527 {
528     return getBuffer()[pos];
529 }
530 
find(char ch) const531 size_t SimpleString::find(char ch) const
532 {
533     return findFrom(0, ch);
534 }
535 
findFrom(size_t starting_position,char ch) const536 size_t SimpleString::findFrom(size_t starting_position, char ch) const
537 {
538     size_t length = size();
539     for (size_t i = starting_position; i < length; i++)
540         if (at(i) == ch) return i;
541     return npos;
542 }
543 
subStringFromTill(char startChar,char lastExcludedChar) const544 SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedChar) const
545 {
546     size_t beginPos = find(startChar);
547     if (beginPos == npos) return "";
548 
549     size_t endPos = findFrom(beginPos, lastExcludedChar);
550     if (endPos == npos) return subString(beginPos);
551 
552     return subString(beginPos, endPos - beginPos);
553 }
554 
copyToNewBuffer(const char * bufferToCopy,size_t bufferSize)555 char* SimpleString::copyToNewBuffer(const char* bufferToCopy, size_t bufferSize)
556 {
557     char* newBuffer = allocStringBuffer(bufferSize, __FILE__, __LINE__);
558     StrNCpy(newBuffer, bufferToCopy, bufferSize);
559     newBuffer[bufferSize-1] = '\0';
560     return newBuffer;
561 }
562 
563 
copyToBuffer(char * bufferToCopy,size_t bufferSize) const564 void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const
565 {
566     if (bufferToCopy == NULLPTR || bufferSize == 0) return;
567 
568     size_t sizeToCopy = (bufferSize-1 < size()) ? (bufferSize-1) : size();
569 
570     StrNCpy(bufferToCopy, getBuffer(), sizeToCopy);
571     bufferToCopy[sizeToCopy] = '\0';
572 }
573 
isDigit(char ch)574 bool SimpleString::isDigit(char ch)
575 {
576     return '0' <= ch && '9' >= ch;
577 }
578 
isSpace(char ch)579 bool SimpleString::isSpace(char ch)
580 {
581     return (ch == ' ') || (0x08 < ch && 0x0E > ch);
582 }
583 
isUpper(char ch)584 bool SimpleString::isUpper(char ch)
585 {
586     return 'A' <= ch && 'Z' >= ch;
587 }
588 
StringFrom(bool value)589 SimpleString StringFrom(bool value)
590 {
591     return SimpleString(StringFromFormat("%s", value ? "true" : "false"));
592 }
593 
StringFrom(const char * value)594 SimpleString StringFrom(const char *value)
595 {
596     return SimpleString(value);
597 }
598 
StringFromOrNull(const char * expected)599 SimpleString StringFromOrNull(const char * expected)
600 {
601     return (expected) ? StringFrom(expected) : "(null)";
602 }
603 
StringFrom(int value)604 SimpleString StringFrom(int value)
605 {
606     return StringFromFormat("%d", value);
607 }
608 
StringFrom(long value)609 SimpleString StringFrom(long value)
610 {
611     return StringFromFormat("%ld", value);
612 }
613 
StringFrom(const void * value)614 SimpleString StringFrom(const void* value)
615 {
616     return SimpleString("0x") + HexStringFrom(value);
617 }
618 
StringFrom(void (* value)())619 SimpleString StringFrom(void (*value)())
620 {
621     return SimpleString("0x") + HexStringFrom(value);
622 }
623 
HexStringFrom(long value)624 SimpleString HexStringFrom(long value)
625 {
626     return StringFromFormat("%lx", value);
627 }
628 
HexStringFrom(int value)629 SimpleString HexStringFrom(int value)
630 {
631     return StringFromFormat("%x", value);
632 }
633 
HexStringFrom(signed char value)634 SimpleString HexStringFrom(signed char value)
635 {
636     SimpleString result = StringFromFormat("%x", value);
637     if(value < 0) {
638         size_t size = result.size();
639         result = result.subString(size-(CPPUTEST_CHAR_BIT/4));
640     }
641     return result;
642 }
643 
HexStringFrom(unsigned long value)644 SimpleString HexStringFrom(unsigned long value)
645 {
646     return StringFromFormat("%lx", value);
647 }
648 
HexStringFrom(unsigned int value)649 SimpleString HexStringFrom(unsigned int value)
650 {
651     return StringFromFormat("%x", value);
652 }
653 
BracketsFormattedHexStringFrom(int value)654 SimpleString BracketsFormattedHexStringFrom(int value)
655 {
656     return BracketsFormattedHexString(HexStringFrom(value));
657 }
658 
BracketsFormattedHexStringFrom(unsigned int value)659 SimpleString BracketsFormattedHexStringFrom(unsigned int value)
660 {
661     return BracketsFormattedHexString(HexStringFrom(value));
662 }
663 
BracketsFormattedHexStringFrom(long value)664 SimpleString BracketsFormattedHexStringFrom(long value)
665 {
666     return BracketsFormattedHexString(HexStringFrom(value));
667 }
668 
669 
BracketsFormattedHexStringFrom(unsigned long value)670 SimpleString BracketsFormattedHexStringFrom(unsigned long value)
671 {
672     return BracketsFormattedHexString(HexStringFrom(value));
673 }
674 
BracketsFormattedHexStringFrom(signed char value)675 SimpleString BracketsFormattedHexStringFrom(signed char value)
676 {
677     return BracketsFormattedHexString(HexStringFrom(value));
678 }
679 
BracketsFormattedHexString(SimpleString hexString)680 SimpleString BracketsFormattedHexString(SimpleString hexString)
681 {
682     return SimpleString("(0x") + hexString + ")" ;
683 }
684 
685 /*
686  * ARM compiler has only partial support for C++11.
687  * Specifically nullptr_t is not officially supported
688  */
689 #if __cplusplus > 199711L && !defined __arm__ && CPPUTEST_USE_STD_CPP_LIB
StringFrom(const std::nullptr_t value)690 SimpleString StringFrom(const std::nullptr_t value)
691 {
692     (void) value;
693     return "(null)";
694 }
695 #endif
696 
697 #ifdef CPPUTEST_USE_LONG_LONG
698 
StringFrom(cpputest_longlong value)699 SimpleString StringFrom(cpputest_longlong value)
700 {
701     return StringFromFormat("%lld", value);
702 }
703 
StringFrom(cpputest_ulonglong value)704 SimpleString StringFrom(cpputest_ulonglong value)
705 {
706     return StringFromFormat("%llu", value);
707 }
708 
HexStringFrom(cpputest_longlong value)709 SimpleString HexStringFrom(cpputest_longlong value)
710 {
711     return StringFromFormat("%llx", value);
712 }
713 
HexStringFrom(cpputest_ulonglong value)714 SimpleString HexStringFrom(cpputest_ulonglong value)
715 {
716     return StringFromFormat("%llx", value);
717 }
718 
HexStringFrom(const void * value)719 SimpleString HexStringFrom(const void* value)
720 {
721     return HexStringFrom((cpputest_ulonglong) value);
722 }
723 
HexStringFrom(void (* value)())724 SimpleString HexStringFrom(void (*value)())
725 {
726     return HexStringFrom((cpputest_ulonglong) value);
727 }
728 
BracketsFormattedHexStringFrom(cpputest_longlong value)729 SimpleString BracketsFormattedHexStringFrom(cpputest_longlong value)
730 {
731     return BracketsFormattedHexString(HexStringFrom(value));
732 }
733 
734 
BracketsFormattedHexStringFrom(cpputest_ulonglong value)735 SimpleString BracketsFormattedHexStringFrom(cpputest_ulonglong value)
736 {
737     return BracketsFormattedHexString(HexStringFrom(value));
738 }
739 
740 #else   /* CPPUTEST_USE_LONG_LONG */
741 
convertPointerToLongValue(const void * value)742 static long convertPointerToLongValue(const void* value)
743 {
744     /*
745      * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating.
746      * This isn't the right way to convert pointers values and need to change by implementing a
747      * proper portable way to convert pointers to strings.
748      */
749     long* long_value = (long*) &value;
750     return *long_value;
751 }
752 
convertFunctionPointerToLongValue(void (* value)())753 static long convertFunctionPointerToLongValue(void (*value)())
754 {
755     /*
756      * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating.
757      * This isn't the right way to convert pointers values and need to change by implementing a
758      * proper portable way to convert pointers to strings.
759      */
760     long* long_value = (long*) &value;
761     return *long_value;
762 }
763 
StringFrom(cpputest_longlong)764 SimpleString StringFrom(cpputest_longlong)
765 {
766     return "<longlong_unsupported>";
767 }
768 
StringFrom(cpputest_ulonglong)769 SimpleString StringFrom(cpputest_ulonglong)
770 {
771     return "<ulonglong_unsupported>";
772 }
773 
HexStringFrom(cpputest_longlong)774 SimpleString HexStringFrom(cpputest_longlong)
775 {
776     return "<longlong_unsupported>";
777 }
778 
HexStringFrom(cpputest_ulonglong)779 SimpleString HexStringFrom(cpputest_ulonglong)
780 {
781     return "<ulonglong_unsupported>";
782 }
783 
HexStringFrom(const void * value)784 SimpleString HexStringFrom(const void* value)
785 {
786     return StringFromFormat("%lx", convertPointerToLongValue(value));
787 }
788 
HexStringFrom(void (* value)())789 SimpleString HexStringFrom(void (*value)())
790 {
791     return StringFromFormat("%lx", convertFunctionPointerToLongValue(value));
792 }
793 
BracketsFormattedHexStringFrom(cpputest_longlong)794 SimpleString BracketsFormattedHexStringFrom(cpputest_longlong)
795 {
796     return "";
797 }
798 
799 
BracketsFormattedHexStringFrom(cpputest_ulonglong)800 SimpleString BracketsFormattedHexStringFrom(cpputest_ulonglong)
801 {
802     return "";
803 }
804 
805 #endif  /* CPPUTEST_USE_LONG_LONG */
806 
StringFrom(double value,int precision)807 SimpleString StringFrom(double value, int precision)
808 {
809     if (PlatformSpecificIsNan(value))
810         return "Nan - Not a number";
811     else if (PlatformSpecificIsInf(value))
812         return "Inf - Infinity";
813     else
814         return StringFromFormat("%.*g", precision, value);
815 }
816 
StringFrom(char value)817 SimpleString StringFrom(char value)
818 {
819     return StringFromFormat("%c", value);
820 }
821 
StringFrom(const SimpleString & value)822 SimpleString StringFrom(const SimpleString& value)
823 {
824     return SimpleString(value);
825 }
826 
StringFromFormat(const char * format,...)827 SimpleString StringFromFormat(const char* format, ...)
828 {
829     SimpleString resultString;
830     va_list arguments;
831     va_start(arguments, format);
832 
833     resultString = VStringFromFormat(format, arguments);
834     va_end(arguments);
835     return resultString;
836 }
837 
StringFrom(unsigned int i)838 SimpleString StringFrom(unsigned int i)
839 {
840     return StringFromFormat("%u", i);
841 }
842 
843 #if CPPUTEST_USE_STD_CPP_LIB
844 
845 #include <string>
846 
StringFrom(const std::string & value)847 SimpleString StringFrom(const std::string& value)
848 {
849     return SimpleString(value.c_str());
850 }
851 
852 #endif
853 
StringFrom(unsigned long i)854 SimpleString StringFrom(unsigned long i)
855 {
856     return StringFromFormat("%lu", i);
857 }
858 
VStringFromFormat(const char * format,va_list args)859 SimpleString VStringFromFormat(const char* format, va_list args)
860 {
861     va_list argsCopy;
862     va_copy(argsCopy, args);
863     enum
864     {
865         sizeOfdefaultBuffer = 100
866     };
867     char defaultBuffer[sizeOfdefaultBuffer];
868     SimpleString resultString;
869 
870     size_t size = (size_t)PlatformSpecificVSNprintf(defaultBuffer, sizeOfdefaultBuffer, format, args);
871     if (size < sizeOfdefaultBuffer) {
872         resultString = SimpleString(defaultBuffer);
873     }
874     else {
875         size_t newBufferSize = size + 1;
876         char* newBuffer = SimpleString::allocStringBuffer(newBufferSize, __FILE__, __LINE__);
877         PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy);
878         resultString = SimpleString(newBuffer);
879 
880         SimpleString::deallocStringBuffer(newBuffer, newBufferSize, __FILE__, __LINE__);
881     }
882     va_end(argsCopy);
883     return resultString;
884 }
885 
StringFromBinary(const unsigned char * value,size_t size)886 SimpleString StringFromBinary(const unsigned char* value, size_t size)
887 {
888     SimpleString result;
889 
890     for (size_t i = 0; i < size; i++) {
891         result += StringFromFormat("%02X ", value[i]);
892     }
893     result = result.subString(0, result.size() - 1);
894 
895     return result;
896 }
897 
StringFromBinaryOrNull(const unsigned char * value,size_t size)898 SimpleString StringFromBinaryOrNull(const unsigned char* value, size_t size)
899 {
900     return (value) ? StringFromBinary(value, size) : "(null)";
901 }
902 
StringFromBinaryWithSize(const unsigned char * value,size_t size)903 SimpleString StringFromBinaryWithSize(const unsigned char* value, size_t size)
904 {
905     SimpleString result = StringFromFormat("Size = %u | HexContents = ", (unsigned) size);
906     size_t displayedSize = ((size > 128) ? 128 : size);
907     result += StringFromBinaryOrNull(value, displayedSize);
908     if (size > displayedSize)
909     {
910         result += " ...";
911     }
912     return result;
913 }
914 
StringFromBinaryWithSizeOrNull(const unsigned char * value,size_t size)915 SimpleString StringFromBinaryWithSizeOrNull(const unsigned char* value, size_t size)
916 {
917     return (value) ? StringFromBinaryWithSize(value, size) : "(null)";
918 }
919 
StringFromMaskedBits(unsigned long value,unsigned long mask,size_t byteCount)920 SimpleString StringFromMaskedBits(unsigned long value, unsigned long mask, size_t byteCount)
921 {
922     SimpleString result;
923     size_t bitCount = (byteCount > sizeof(unsigned long)) ? (sizeof(unsigned long) * CPPUTEST_CHAR_BIT) : (byteCount * CPPUTEST_CHAR_BIT);
924     const unsigned long msbMask = (((unsigned long) 1) << (bitCount - 1));
925 
926     for (size_t i = 0; i < bitCount; i++) {
927         if (mask & msbMask) {
928             result += (value & msbMask) ? "1" : "0";
929         }
930         else {
931             result += "x";
932         }
933 
934         if (((i % 8) == 7) && (i != (bitCount - 1))) {
935             result += " ";
936         }
937 
938         value <<= 1;
939         mask <<= 1;
940     }
941 
942     return result;
943 }
944 
StringFromOrdinalNumber(unsigned int number)945 SimpleString StringFromOrdinalNumber(unsigned int number)
946 {
947     unsigned int onesDigit = number % 10;
948 
949     const char* suffix;
950     if (number >= 11 && number <= 13) {
951         suffix = "th";
952     } else if (3 == onesDigit) {
953         suffix = "rd";
954     } else if (2 == onesDigit) {
955         suffix = "nd";
956     } else if (1 == onesDigit) {
957         suffix = "st";
958     } else {
959         suffix = "th";
960     }
961 
962     return StringFromFormat("%u%s", number, suffix);
963 }
964 
SimpleStringCollection()965 SimpleStringCollection::SimpleStringCollection()
966 {
967     collection_ = NULLPTR;
968     size_ = 0;
969 }
970 
allocate(size_t _size)971 void SimpleStringCollection::allocate(size_t _size)
972 {
973     delete[] collection_;
974 
975     size_ = _size;
976     collection_ = new SimpleString[size_];
977 }
978 
~SimpleStringCollection()979 SimpleStringCollection::~SimpleStringCollection()
980 {
981     delete[] (collection_);
982 }
983 
size() const984 size_t SimpleStringCollection::size() const
985 {
986     return size_;
987 }
988 
operator [](size_t index)989 SimpleString& SimpleStringCollection::operator[](size_t index)
990 {
991     if (index >= size_) {
992         empty_ = "";
993         return empty_;
994     }
995 
996     return collection_[index];
997 }
998