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