GCC Code Coverage Report


Directory: ./
File: Fw/Types/StringUtils.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 59 60 98.3%
Functions: 5 5 100.0%
Branches: 37 44 84.1%

Line Branch Exec Source
1 #include "StringUtils.hpp"
2 #include <Fw/Types/Assert.hpp>
3 #include <Fw/Types/ExternalString.hpp>
4 #include <cstring>
5 #include <limits>
6
7 20321117 char* Fw::StringUtils::string_copy(char* destination, const char* source, FwSizeType num) {
8 // Handle self-copy and 0 bytes copy
9
2/4
✓ Branch 0 taken 20321117 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20321117 times.
20321117 if (destination == source || num == 0) {
10 return destination;
11 }
12 20321117 FW_ASSERT(source != nullptr);
13 20321117 FW_ASSERT(destination != nullptr);
14
15 // Copying an overlapping range is undefined
16 20321117 FwSizeType source_len = string_length(source, num) + 1;
17 20321117 FW_ASSERT(source + source_len <= destination || destination + num <= source);
18
19
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 20321117 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20321117 times.
20321117 char* returned = strncpy(destination, source, static_cast<size_t>(num));
20 20321117 destination[num - 1] = '\0';
21 20321117 return returned;
22 }
23
24 18 const char* Fw::StringUtils::string_last_n(const char* source, const FwSizeType n, const FwSizeType buffer_size) {
25 18 FW_ASSERT(source != nullptr);
26 18 FwSizeType length = Fw::StringUtils::string_length(source, buffer_size);
27
28 // Calculate start index. If string is shorter than N, keep whole string.
29
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13 times.
18 return (length > n) ? source + (length - n) : source;
30 }
31
32 20447019 FwSizeType Fw::StringUtils::string_length(const CHAR* source, FwSizeType buffer_size) {
33 20447019 FwSizeType length = 0;
34 20447019 FW_ASSERT(source != nullptr);
35
2/2
✓ Branch 0 taken 41535613 times.
✓ Branch 1 taken 3510 times.
41539123 for (length = 0; length < buffer_size; length++) {
36
2/2
✓ Branch 2 taken 20443509 times.
✓ Branch 3 taken 21092104 times.
41535613 if (source[length] == '\0') {
37 20443509 break;
38 }
39 }
40 20447019 return length;
41 }
42
43 4356 FwSignedSizeType Fw::StringUtils::substring_find(const CHAR* source_string,
44 FwSizeType source_size,
45 const CHAR* sub_string,
46 FwSizeType sub_size) {
47 4356 FW_ASSERT(source_string != nullptr);
48 4356 FW_ASSERT(sub_string != nullptr);
49
50 // zero size sub-strings should always match, including in an empty source
51
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4354 times.
4356 if (0 == sub_size) {
52 2 return 0;
53 }
54
55 // Cannot find a substring larger than the source
56
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4353 times.
4354 if (source_size < sub_size) {
57 1 return -1;
58 }
59 // Confirm that the output type can hold the range of valid results
60 4353 FW_ASSERT(source_size - sub_size <= static_cast<FwSizeType>(std::numeric_limits<FwSignedSizeType>::max()));
61
62 // Loop from zero to source_size - sub_size (inclusive)
63 7321 for (FwSizeType source_index = 0;
64
4/4
✓ Branch 0 taken 5834 times.
✓ Branch 1 taken 1487 times.
✓ Branch 2 taken 5834 times.
✓ Branch 3 taken 1487 times.
13155 source_index < (source_size - sub_size + 1) &&
65
1/2
✓ Branch 1 taken 5834 times.
✗ Branch 2 not taken.
5834 source_index < static_cast<FwSizeType>(std::numeric_limits<FwSignedSizeType>::max());
66 source_index++) {
67 // if the current character matches
68
1/2
✓ Branch 0 taken 81593 times.
✗ Branch 1 not taken.
81593 for (FwSizeType sub_index = 0; sub_index < sub_size; sub_index++) {
69 // Prevent read overrun
70 81593 FW_ASSERT((source_index + sub_index) < source_size);
71 // if there is a mismatch, go to next character
72
2/2
✓ Branch 4 taken 2968 times.
✓ Branch 5 taken 78625 times.
81593 if (source_string[source_index + sub_index] != sub_string[sub_index]) {
73 2968 break;
74
2/2
✓ Branch 0 taken 2866 times.
✓ Branch 1 taken 75759 times.
78625 } else if (sub_index == (sub_size - 1)) {
75 // if we matched all the way to the end of the substring
76 2866 return static_cast<FwSignedSizeType>(source_index);
77 }
78 }
79 }
80
81 // if we make it here, no matches were found
82 1487 return -1;
83 }
84
85 6500 FwSignedSizeType Fw::StringUtils::substring_find_last(const CHAR* source_string,
86 FwSizeType source_size,
87 const CHAR* sub_string,
88 FwSizeType sub_size) {
89 6500 FW_ASSERT(source_string != nullptr);
90 6500 FW_ASSERT(sub_string != nullptr);
91
92 6500 FwSizeType match_index = 0;
93
94 // zero size sub-strings should always match
95
4/4
✓ Branch 0 taken 6499 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6498 times.
6500 if ((source_size > 0) && (0 == sub_size)) {
96 1 match_index = source_size - 1;
97
98 // Ensure we can represent the match_index in a signed num
99 FW_ASSERT(static_cast<FwSizeType>(static_cast<FwSignedSizeType>(match_index)) == match_index);
100
101 1 return static_cast<FwSignedSizeType>(match_index);
102 }
103
104 // Cannot find a substring larger than the source
105
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6498 times.
6499 if (source_size < sub_size) {
106 1 return -1;
107 }
108 // Confirm that the output type can hold the range of valid results
109 6498 FW_ASSERT(source_size - sub_size <= static_cast<FwSizeType>(std::numeric_limits<FwSignedSizeType>::max()));
110
111 // Loop from source_size - sub_size to zero (inclusive)
112 6498 const FwSizeType max_start_index = source_size - sub_size;
113
2/2
✓ Branch 0 taken 102612 times.
✓ Branch 1 taken 320 times.
102932 for (FwSizeType ii = 0; ii <= max_start_index; ii++) {
114 102612 const FwSizeType source_index = max_start_index - ii;
115
116 // if the current character matches
117
1/2
✓ Branch 0 taken 113889 times.
✗ Branch 1 not taken.
113889 for (FwSizeType sub_index = 0; sub_index < sub_size; sub_index++) {
118 // Prevent read overrun
119 113889 FW_ASSERT((source_index + sub_index) < source_size);
120 // if there is a mismatch, go to next character
121
2/2
✓ Branch 4 taken 96434 times.
✓ Branch 5 taken 17455 times.
113889 if (source_string[source_index + sub_index] != sub_string[sub_index]) {
122 96434 break;
123
2/2
✓ Branch 0 taken 6178 times.
✓ Branch 1 taken 11277 times.
17455 } else if (sub_index == (sub_size - 1)) {
124 // if we matched all the way to the end of the substring
125 6178 match_index = source_index;
126
127 // Ensure the result converts properly
128 FW_ASSERT(static_cast<FwSizeType>(static_cast<FwSignedSizeType>(match_index)) == match_index);
129
130 6178 return static_cast<FwSignedSizeType>(match_index);
131 }
132 }
133 }
134
135 // if we make it here, no matches were found
136 320 return -1;
137 }
138