• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

thetic / mutiny / 24009085345

05 Apr 2026 07:46PM UTC coverage: 98.971%. Remained the same
24009085345

Pull #28

github

web-flow
Merge f94b1b372 into 9ac355afb
Pull Request #28: Fix duplicate CI runs on branches with open PRs

5576 of 5634 relevant lines covered (98.97%)

3588.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.88
/src/String.cpp
1
#include "mutiny/String.hpp"
2

3
#include "mutiny/math.hpp"
4

5
#if MUTINY_USE_STD_CPP_LIB
6
#include <string>
7
#endif
8

9
#if MUTINY_USE_STD_STRING
10
#include <cctype>
11
#include <cstdlib>
12
#include <cstring>
13
#endif
14

15
#include <inttypes.h>
16
#include <limits.h>
17
#include <stdint.h>
18
#include <stdio.h>
19

20
namespace mu {
21
namespace tiny {
22

23
namespace {
24
#if !MUTINY_USE_STD_STRING
25
char* str_n_cpy(char* s1, const char* s2, size_t n)
139,084✔
26
{
27
  char* result = s1;
139,084✔
28

29
  if ((nullptr == s1) || (0 == n))
139,084✔
30
    return result;
×
31

32
  *s1 = *s2;
139,084✔
33
  while ((--n != 0) && *s1) {
2,577,136✔
34
    *++s1 = *++s2;
2,438,052✔
35
  }
36
  return result;
139,084✔
37
}
38

39
char* copy_to_new_buffer(const char* buffer_to_copy, size_t buffer_size)
96,141✔
40
{
41
  char* new_buffer = new char[buffer_size];
96,141✔
42
  str_n_cpy(new_buffer, buffer_to_copy, buffer_size);
96,141✔
43
  if (buffer_size > 0)
96,141✔
44
    new_buffer[buffer_size - 1] = '\0';
96,141✔
45
  return new_buffer;
96,141✔
46
}
47
#endif
48

49
#if !MUTINY_USE_STD_STRING
50
bool is_digit(char ch)
117✔
51
{
52
  return '0' <= ch && '9' >= ch;
117✔
53
}
54

55
bool is_space(char ch)
39✔
56
{
57
  return (ch == ' ') || (0x08 < ch && 0x0E > ch);
39✔
58
}
59

60
bool is_upper(char ch)
32✔
61
{
62
  return 'A' <= ch && 'Z' >= ch;
32✔
63
}
64
#endif
65
} // namespace
66

67
#if !MUTINY_USE_STD_STRING
68
char* String::get_empty_string() const
13✔
69
{
70
  char* buf = new char[1];
13✔
71
  buf[0] = '\0';
13✔
72
  return buf;
13✔
73
}
74

75
void String::deallocate_internal_buffer()
207,138✔
76
{
77
  if (buffer_) {
207,138✔
78
    delete[] buffer_;
96,381✔
79
    buffer_ = nullptr;
96,381✔
80
    buffer_size_ = 0;
96,381✔
81
    size_ = 0;
96,381✔
82
  }
83
}
207,138✔
84

85
void String::set_internal_buffer_as_empty_string()
13✔
86
{
87
  deallocate_internal_buffer();
13✔
88

89
  buffer_size_ = 1;
13✔
90
  buffer_ = get_empty_string();
13✔
91
}
13✔
92

93
void String::copy_buffer_to_new_internal_buffer(
96,141✔
94
    const char* other_buffer,
95
    size_t buffer_size
96
)
97
{
98
  deallocate_internal_buffer();
96,141✔
99

100
  buffer_size_ = buffer_size;
96,141✔
101
  size_ = buffer_size_ - 1;
96,141✔
102
  buffer_ = copy_to_new_buffer(other_buffer, buffer_size_);
96,141✔
103
}
96,141✔
104

105
void String::reserve(size_t new_capacity)
244✔
106
{
107
  size_t needed = new_capacity + 1;
244✔
108
  if (needed <= buffer_size_)
244✔
109
    return;
1✔
110

111
  char* new_buffer = new char[needed];
243✔
112
  str_n_cpy(new_buffer, buffer_, buffer_size_);
243✔
113
  new_buffer[needed - 1] = '\0';
243✔
114
  delete[] buffer_;
243✔
115
  buffer_ = new_buffer;
243✔
116
  buffer_size_ = needed;
243✔
117
  // size_ is unchanged: the string content was preserved
118
}
119

120
void String::clear()
13✔
121
{
122
  set_internal_buffer_as_empty_string();
13✔
123
}
13✔
124

125
void String::copy_buffer_to_new_internal_buffer(const String& other_buffer)
1,011✔
126
{
127
  copy_buffer_to_new_internal_buffer(
1,011✔
128
      other_buffer.buffer_, other_buffer.size() + 1
1,011✔
129
  );
130
}
1,011✔
131

132
void String::copy_buffer_to_new_internal_buffer(const char* other_buffer)
95,130✔
133
{
134
  copy_buffer_to_new_internal_buffer(other_buffer, strlen(other_buffer) + 1);
95,130✔
135
}
95,130✔
136

137
String::String(const char* other_buffer)
85,771✔
138
  : buffer_(nullptr)
85,771✔
139
  , buffer_size_(0)
85,771✔
140
  , size_(0)
85,771✔
141
{
142
  if (other_buffer == nullptr)
85,771✔
143
    set_internal_buffer_as_empty_string();
×
144
  else
145
    copy_buffer_to_new_internal_buffer(other_buffer);
85,771✔
146
}
85,771✔
147

148
String::String(size_t count, char ch)
239✔
149
  : buffer_(nullptr)
239✔
150
  , buffer_size_(0)
239✔
151
  , size_(0)
239✔
152
{
153
  buffer_size_ = count + 1;
239✔
154
  size_ = count;
239✔
155
  buffer_ = new char[buffer_size_];
239✔
156
  for (size_t i = 0; i < count; i++)
3,428✔
157
    buffer_[i] = ch;
3,189✔
158
  buffer_[count] = '\0';
239✔
159
}
239✔
160

161
String::String(const String& other)
9,359✔
162
  : buffer_(nullptr)
9,359✔
163
  , buffer_size_(0)
9,359✔
164
  , size_(0)
9,359✔
165
{
166
  copy_buffer_to_new_internal_buffer(other.c_str());
9,359✔
167
}
9,359✔
168

169
String::String(String&& other) noexcept
2,793✔
170
  : buffer_(other.buffer_)
2,793✔
171
  , buffer_size_(other.buffer_size_)
2,793✔
172
  , size_(other.size_)
2,793✔
173
{
174
  other.buffer_ = nullptr;
2,793✔
175
  other.buffer_size_ = 0;
2,793✔
176
  other.size_ = 0;
2,793✔
177
}
2,793✔
178

179
String& String::operator=(String&& other) noexcept
12,957✔
180
{
181
  if (this != &other) {
12,957✔
182
    deallocate_internal_buffer();
12,957✔
183
    buffer_ = other.buffer_;
12,957✔
184
    buffer_size_ = other.buffer_size_;
12,957✔
185
    size_ = other.size_;
12,957✔
186
    other.buffer_ = nullptr;
12,957✔
187
    other.buffer_size_ = 0;
12,957✔
188
    other.size_ = 0;
12,957✔
189
  }
190
  return *this;
12,957✔
191
}
192

193
String& String::operator=(const String& other)
1,011✔
194
{
195
  if (this != &other)
1,011✔
196
    copy_buffer_to_new_internal_buffer(other);
1,011✔
197
  return *this;
1,011✔
198
}
199

200
const char* String::c_str() const
131,347✔
201
{
202
  return buffer_;
131,347✔
203
}
204

205
const char* String::data() const
1✔
206
{
207
  return buffer_;
1✔
208
}
209

210
char* String::data()
10,320✔
211
{
212
  return buffer_;
10,320✔
213
}
214

215
size_t String::size() const
5,665✔
216
{
217
  return size_;
5,665✔
218
}
219

220
bool String::empty() const
1,142✔
221
{
222
  return size_ == 0;
1,142✔
223
}
224

225
String::~String()
98,027✔
226
{
227
  deallocate_internal_buffer();
98,027✔
228
}
98,027✔
229

230
bool operator==(const String& left, const String& right)
49,249✔
231
{
232
  return 0 == strcmp(left.c_str(), right.c_str());
49,249✔
233
}
234

235
bool operator!=(const String& left, const String& right)
2,761✔
236
{
237
  return !(left == right);
2,761✔
238
}
239

240
String String::operator+(const String& rhs) const
865✔
241
{
242
  String t(c_str());
865✔
243
  t += rhs.c_str();
865✔
244
  return t;
865✔
245
}
×
246

247
String& String::operator+=(const String& rhs)
5,010✔
248
{
249
  return operator+=(rhs.c_str());
5,010✔
250
}
251

252
String& String::operator+=(const char* rhs)
27,255✔
253
{
254
  size_t rhs_len = strlen(rhs);
27,255✔
255
  size_t new_size = size_ + rhs_len;
27,255✔
256
  size_t needed = new_size + 1;
27,255✔
257
  if (needed <= buffer_size_) {
27,255✔
258
    str_n_cpy(buffer_ + size_, rhs, rhs_len + 1);
11,810✔
259
  } else {
260
    size_t new_cap = buffer_size_ * 2;
15,445✔
261
    if (new_cap < needed)
15,445✔
262
      new_cap = needed;
4,523✔
263
    char* nb = new char[new_cap];
15,445✔
264
    str_n_cpy(nb, buffer_, size_ + 1);
15,445✔
265
    str_n_cpy(nb + size_, rhs, rhs_len + 1);
15,445✔
266
    delete[] buffer_;
15,445✔
267
    buffer_ = nb;
15,445✔
268
    buffer_size_ = new_cap;
15,445✔
269
  }
270
  size_ = new_size;
27,255✔
271
  return *this;
27,255✔
272
}
273

274
String& String::operator+=(char ch)
1,193✔
275
{
276
  size_t needed = size_ + 2;
1,193✔
277
  if (needed <= buffer_size_) {
1,193✔
278
    buffer_[size_] = ch;
1,191✔
279
    buffer_[size_ + 1] = '\0';
1,191✔
280
    size_ += 1;
1,191✔
281
    return *this;
1,191✔
282
  }
283
  char tmp[2] = { ch, '\0' };
2✔
284
  return operator+=(tmp);
2✔
285
}
286

287
void String::resize(size_t new_size)
106✔
288
{
289
  reserve(new_size);
106✔
290
  buffer_[new_size] = '\0';
106✔
291
  size_ = new_size;
106✔
292
}
106✔
293

294
String String::substr(size_t begin_pos, size_t amount) const
1,062✔
295
{
296
  if (begin_pos > size() - 1)
1,062✔
297
    return "";
6✔
298

299
  String new_string = c_str() + begin_pos;
1,056✔
300

301
  if (new_string.size_ > amount) {
1,056✔
302
    new_string.buffer_[amount] = '\0';
942✔
303
    new_string.size_ = amount;
942✔
304
  }
305

306
  return new_string;
1,056✔
307
}
1,056✔
308

309
String String::substr(size_t begin_pos) const
33✔
310
{
311
  return substr(begin_pos, npos);
33✔
312
}
313

314
size_t String::find(char ch, size_t pos) const
18✔
315
{
316
  size_t len = size();
18✔
317
  for (size_t i = pos; i < len; i++)
105✔
318
    if (c_str()[i] == ch)
102✔
319
      return i;
15✔
320
  return npos;
3✔
321
}
322

323
size_t String::find(const char* s, size_t pos) const
495✔
324
{
325
  if (pos > size())
495✔
326
    return npos;
×
327
  const char* found = strstr(c_str() + pos, s);
495✔
328
  if (found == nullptr)
495✔
329
    return npos;
446✔
330
  return static_cast<size_t>(found - c_str());
49✔
331
}
332

333
bool operator<(const String& left, const String& right)
3✔
334
{
335
  return strcmp(left.c_str(), right.c_str()) < 0;
3✔
336
}
337
#endif
338

339
bool string_contains(const String& str, const String& substr)
724✔
340
{
341
  return strstr(str.c_str(), substr.c_str()) != nullptr;
724✔
342
}
343

344
bool string_starts_with(const String& str, const String& prefix)
918✔
345
{
346
  if (prefix.size() == 0)
918✔
347
    return true;
1✔
348
  else if (str.size() == 0)
917✔
349
    return false;
1✔
350
  else
351
    return strstr(str.c_str(), prefix.c_str()) == str.c_str();
916✔
352
}
353

354
bool string_ends_with(const String& str, const String& suffix)
102✔
355
{
356
  size_t len = str.size();
102✔
357
  size_t other_len = suffix.size();
102✔
358

359
  if (other_len == 0)
102✔
360
    return true;
1✔
361
  if (len == 0)
101✔
362
    return false;
1✔
363
  if (len < other_len)
100✔
364
    return false;
1✔
365

366
  return strcmp(str.c_str() + len - other_len, suffix.c_str()) == 0;
99✔
367
}
368

369
void string_replace(String& str, char from, char to)
471✔
370
{
371
  size_t s = str.size();
471✔
372
  for (size_t i = 0; i < s; i++) {
10,401✔
373
    if (str[i] == from)
9,930✔
374
      str[i] = to;
26✔
375
  }
376
}
471✔
377

378
void string_replace(String& str, const char* from, const char* to)
445✔
379
{
380
  size_t fromlen = strlen(from);
445✔
381
  if (fromlen == 0)
445✔
382
    return;
423✔
383

384
  String result;
444✔
385
  size_t pos = 0;
444✔
386
  size_t found = str.find(from, pos);
444✔
387
  while (found != String::npos) {
485✔
388
    result += str.substr(pos, found - pos);
41✔
389
    result += to;
41✔
390
    pos = found + fromlen;
41✔
391
    found = str.find(from, pos);
41✔
392
  }
393
  if (pos == 0)
444✔
394
    return;
422✔
395
  result += str.substr(pos);
22✔
396
  str = result;
22✔
397
}
444✔
398

399
long strtol(const char* str)
12✔
400
{
401
#if MUTINY_USE_STD_STRING
402
  return std::strtol(str, nullptr, 10);
403
#else
404
  while (is_space(*str))
16✔
405
    str++;
4✔
406

407
  char first_char = *str;
12✔
408
  if (first_char == '-' || first_char == '+')
12✔
409
    str++;
3✔
410

411
  long result = 0;
12✔
412
  for (; is_digit(*str); str++) {
55✔
413
    result *= 10;
43✔
414
    result += *str - '0';
43✔
415
  }
416
  return (first_char == '-') ? -result : result;
12✔
417
#endif
418
}
419

420
unsigned long strtoul(const char* str)
18✔
421
{
422
#if MUTINY_USE_STD_STRING
423
  return std::strtoul(str, nullptr, 10);
424
#else
425
  while (is_space(*str))
23✔
426
    str++;
5✔
427

428
  bool negative = (*str == '-');
18✔
429
  if (*str == '-' || *str == '+')
18✔
430
    str++;
3✔
431

432
  unsigned long result = 0;
18✔
433
  for (; is_digit(*str); str++) {
62✔
434
    result *= 10;
44✔
435
    result += static_cast<unsigned long>(*str - '0');
44✔
436
  }
437
  return negative ? -result : result;
18✔
438
#endif
439
}
440

441
int strcmp(const char* s1, const char* s2)
50,366✔
442
{
443
#if MUTINY_USE_STD_STRING
444
  return std::strcmp(s1, s2);
445
#else
446
  while (*s1 && *s1 == *s2) {
149,380✔
447
    ++s1;
99,014✔
448
    ++s2;
99,014✔
449
  }
450
  return *reinterpret_cast<const unsigned char*>(s1) -
50,366✔
451
         *reinterpret_cast<const unsigned char*>(s2);
50,366✔
452
#endif
453
}
454

455
size_t strlen(const char* str)
126,880✔
456
{
457
#if MUTINY_USE_STD_STRING
458
  return std::strlen(str);
459
#else
460
  auto n = static_cast<size_t>(-1);
126,880✔
461
  do
462
    n++;
2,001,318✔
463
  while (*str++);
2,001,318✔
464
  return n;
126,880✔
465
#endif
466
}
467

468
int strncmp(const char* s1, const char* s2, size_t n)
120,164✔
469
{
470
#if MUTINY_USE_STD_STRING
471
  return std::strncmp(s1, s2, n);
472
#else
473
  while (n && *s1 && *s1 == *s2) {
144,337✔
474
    --n;
24,173✔
475
    ++s1;
24,173✔
476
    ++s2;
24,173✔
477
  }
478
  return n ? *reinterpret_cast<const unsigned char*>(s1) -
120,164✔
479
                 *reinterpret_cast<const unsigned char*>(s2)
117,480✔
480
           : 0;
120,164✔
481
#endif
482
}
483

484
const char* strstr(const char* s1, const char* s2)
4,057✔
485
{
486
#if MUTINY_USE_STD_STRING
487
  return std::strstr(s1, s2);
488
#else
489
  if (!*s2)
4,057✔
490
    return s1;
7✔
491
  size_t s2_len = strlen(s2);
4,050✔
492
  for (; *s1; s1++)
121,518✔
493
    if (strncmp(s1, s2, s2_len) == 0)
120,144✔
494
      return s1;
2,676✔
495
  return nullptr;
1,374✔
496
#endif
497
}
498

499
char tolower(char ch)
32✔
500
{
501
#if MUTINY_USE_STD_STRING
502
  return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
503
#else
504
  return is_upper(ch) ? static_cast<char>(static_cast<int>(ch) + ('a' - 'A'))
32✔
505
                      : ch;
32✔
506
#endif
507
}
508

509
int memcmp(const void* s1, const void* s2, size_t n)
21✔
510
{
511
#if MUTINY_USE_STD_STRING
512
  return std::memcmp(s1, s2, n);
513
#else
514
  auto* p1 = static_cast<const unsigned char*>(s1);
21✔
515
  auto* p2 = static_cast<const unsigned char*>(s2);
21✔
516

517
  while (n--)
74✔
518
    if (*p1 != *p2) {
63✔
519
      return *p1 - *p2;
10✔
520
    } else {
521
      ++p1;
53✔
522
      ++p2;
53✔
523
    }
524
  return 0;
11✔
525
#endif
526
}
527

528
bool iscntrl(char ch)
818✔
529
{
530
#if MUTINY_USE_STD_STRING
531
  return std::iscntrl(static_cast<unsigned char>(ch)) != 0;
532
#else
533
  return ch < ' ' || ch == char(0x7F);
818✔
534
#endif
535
}
536

537
String string_from(bool value)
4✔
538
{
539
  return String(value ? "true" : "false");
4✔
540
}
541

542
String string_from(const char* value)
127✔
543
{
544
  return String(value);
127✔
545
}
546

547
String string_from_or_null(const char* expected)
13✔
548
{
549
  return (expected) ? string_from(expected) : string_from("(null)");
13✔
550
}
551

552
String string_from(int value)
84✔
553
{
554
  return string_from_format("%d", value);
84✔
555
}
556

557
String string_from(long value)
36✔
558
{
559
  return string_from_format("%ld", value);
36✔
560
}
561

562
String string_from(const void* value)
19✔
563
{
564
  return String("0x") + hex_string_from(value);
19✔
565
}
566

567
String string_from(void (*value)())
7✔
568
{
569
  return String("0x") + hex_string_from(value);
7✔
570
}
571

572
String hex_string_from(long value)
30✔
573
{
574
  return hex_string_from(static_cast<unsigned long>(value));
30✔
575
}
576

577
String hex_string_from(int value)
39✔
578
{
579
  return hex_string_from(static_cast<unsigned int>(value));
39✔
580
}
581

582
String hex_string_from(signed char value)
9✔
583
{
584
  String result = string_from_format("%x", value);
9✔
585
  if (value < 0) {
9✔
586
    size_t size = result.size();
6✔
587
    result = result.substr(size - (CHAR_BIT / 4));
6✔
588
  }
589
  return result;
9✔
590
}
×
591

592
String hex_string_from(unsigned long value)
48✔
593
{
594
  return string_from_format("%lx", value);
48✔
595
}
596

597
String hex_string_from(unsigned int value)
51✔
598
{
599
  return string_from_format("%x", value);
51✔
600
}
601

602
String brackets_formatted_hex_string_from(int value)
39✔
603
{
604
  return brackets_formatted_hex_string(hex_string_from(value));
39✔
605
}
606

607
String brackets_formatted_hex_string_from(unsigned int value)
12✔
608
{
609
  return brackets_formatted_hex_string(hex_string_from(value));
12✔
610
}
611

612
String brackets_formatted_hex_string_from(long value)
29✔
613
{
614
  return brackets_formatted_hex_string(hex_string_from(value));
29✔
615
}
616

617
String brackets_formatted_hex_string_from(unsigned long value)
18✔
618
{
619
  return brackets_formatted_hex_string(hex_string_from(value));
18✔
620
}
621

622
String brackets_formatted_hex_string_from(signed char value)
7✔
623
{
624
  return brackets_formatted_hex_string(hex_string_from(value));
7✔
625
}
626

627
String brackets_formatted_hex_string(const String& hex_string)
131✔
628
{
629
  return String("(0x") + hex_string + ")";
262✔
630
}
631

632
#if MUTINY_USE_STD_CPP_LIB
633
String string_from(const std::nullptr_t value)
1✔
634
{
635
  (void)value;
636
  return "(null)";
1✔
637
}
638

639
#if !MUTINY_USE_STD_STRING
640
String string_from(std::string const& str)
1✔
641
{
642
  return String(str.c_str());
1✔
643
}
644
#endif
645
#endif
646

647
String string_from(long long value)
13✔
648
{
649
  return string_from_format("%lld", value);
13✔
650
}
651

652
String string_from(unsigned long long value)
14✔
653
{
654
  return string_from_format("%llu", value);
14✔
655
}
656

657
String hex_string_from(long long value)
14✔
658
{
659
  return hex_string_from(static_cast<unsigned long long>(value));
14✔
660
}
661

662
String hex_string_from(unsigned long long value)
27✔
663
{
664
  return string_from_format("%llx", value);
27✔
665
}
666

667
String hex_string_from(const void* value)
24✔
668
{
669
  return string_from_format("%" PRIxPTR, reinterpret_cast<uintptr_t>(value));
24✔
670
}
671

672
String hex_string_from(void (*value)())
9✔
673
{
674
  return string_from_format("%" PRIxPTR, reinterpret_cast<uintptr_t>(value));
9✔
675
}
676

677
String brackets_formatted_hex_string_from(long long value)
13✔
678
{
679
  return brackets_formatted_hex_string(hex_string_from(value));
13✔
680
}
681

682
String brackets_formatted_hex_string_from(unsigned long long value)
13✔
683
{
684
  return brackets_formatted_hex_string(hex_string_from(value));
13✔
685
}
686

687
String string_from(double value, int precision)
55✔
688
{
689
  if (is_nan(value))
55✔
690
    return "Nan - Not a number";
5✔
691
  else if (is_inf(value))
50✔
692
    return "Inf - Infinity";
4✔
693
  else
694
    return string_from_format("%.*g", precision, value);
46✔
695
}
696

697
String string_from(char value)
99✔
698
{
699
  return String(1, value);
99✔
700
}
701

702
String string_from(const String& value)
1✔
703
{
704
  return String(value);
1✔
705
}
706

707
String string_from_format(const char* format, ...)
5,012✔
708
{
709
  String result_string;
5,012✔
710
  va_list arguments;
711
  va_start(arguments, format);
5,012✔
712

713
  result_string = v_string_from_format(format, arguments);
5,012✔
714
  va_end(arguments);
5,012✔
715
  return result_string;
10,024✔
716
}
×
717

718
String string_from(unsigned int i)
13✔
719
{
720
  return string_from_format("%u", i);
13✔
721
}
722

723
String string_from(unsigned long i)
2,659✔
724
{
725
  return string_from_format("%lu", i);
2,659✔
726
}
727

728
String v_string_from_format(const char* format, va_list args)
5,012✔
729
{
730
  va_list args_copy;
731
  va_copy(args_copy, args);
5,012✔
732
  constexpr size_t size_ofdefault_buffer = 100;
5,012✔
733
  char default_buffer[size_ofdefault_buffer];
734
  String result_string;
5,012✔
735

736
  auto size = static_cast<size_t>(
737
      vsnprintf(default_buffer, size_ofdefault_buffer, format, args)
5,012✔
738
  );
5,012✔
739
  if (size < size_ofdefault_buffer) {
5,012✔
740
    result_string = String(default_buffer);
4,906✔
741
  } else {
742
#if !MUTINY_USE_STD_STRING
743
    result_string.resize(size);
106✔
744
    vsnprintf(result_string.data(), size + 1, format, args_copy);
106✔
745
#else
746
    size_t new_buffer_size = size + 1;
747
    char* new_buffer = new char[new_buffer_size];
748
    vsnprintf(new_buffer, new_buffer_size, format, args_copy);
749
    result_string = String(new_buffer);
750
    delete[] new_buffer;
751
#endif
752
  }
753
  va_end(args_copy);
5,012✔
754
  return result_string;
10,024✔
755
}
×
756

757
String string_from_binary(const unsigned char* value, size_t size)
44✔
758
{
759
  static const char hex_digits[] = "0123456789ABCDEF";
760
  String result;
44✔
761
  if (size == 0)
44✔
762
    return result;
2✔
763
  result.reserve(size * 3 - 1);
42✔
764
  for (size_t i = 0; i < size; i++) {
318✔
765
    if (i > 0)
276✔
766
      result += ' ';
234✔
767
    result += hex_digits[value[i] >> 4];
276✔
768
    result += hex_digits[value[i] & 0xF];
276✔
769
  }
770
  return result;
42✔
771
}
×
772

773
String string_from_binary_or_null(const unsigned char* value, size_t size)
47✔
774
{
775
  return (value) ? string_from_binary(value, size) : string_from("(null)");
47✔
776
}
777

778
String string_from_binary_with_size(const unsigned char* value, size_t size)
17✔
779
{
780
  String result = string_from_format(
781
      "Size = %u | HexContents = ", static_cast<unsigned>(size)
782
  );
17✔
783
  size_t displayed_size = ((size > 128) ? 128 : size);
17✔
784
  result += string_from_binary_or_null(value, displayed_size);
17✔
785
  if (size > displayed_size) {
17✔
786
    result += " ...";
1✔
787
  }
788
  return result;
17✔
789
}
×
790

791
String string_from_binary_with_size_or_null(
15✔
792
    const unsigned char* value,
793
    size_t size
794
)
795
{
796
  return (value) ? string_from_binary_with_size(value, size)
15✔
797
                 : string_from("(null)");
15✔
798
}
799

800
String string_from_ordinal_number(unsigned int number)
33✔
801
{
802
  const char* suffix = "th";
33✔
803

804
  if ((number < 11) || (number > 13)) {
33✔
805
    unsigned int const ones_digit = number % 10;
27✔
806
    if (3 == ones_digit) {
27✔
807
      suffix = "rd";
6✔
808
    } else if (2 == ones_digit) {
21✔
809
      suffix = "nd";
7✔
810
    } else if (1 == ones_digit) {
14✔
811
      suffix = "st";
3✔
812
    }
813
  }
814

815
  return string_from_format("%u%s", number, suffix);
33✔
816
}
817

818
} // namespace tiny
819
} // namespace mu
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc