GCC Code Coverage Report


Directory: ./
File: Fw/Types/StringUtils.cpp
Date: 2026-10-14 21:15:02
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 22305484 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 22305484 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22305484 times.
22305484 if (destination == source || num == 0) {
10 ✗ return destination;
11 }
12 22305484 FW_ASSERT(source != nullptr);
13 22305484 FW_ASSERT(destination != nullptr);
14
15 // Copying an overlapping range is undefined
16 22305484 FwSizeType source_len = string_length(source, num) + 1;
17 22305484 FW_ASSERT(source + source_len <= destination || destination + num <= source);
18
19
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 22305484 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22305484 times.
22305484 char* returned = strncpy(destination, source, static_cast<size_t>(num));
20 22305484 destination[num - 1] = '\0';
21 22305484 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 22434602 FwSizeType Fw::StringUtils::string_length(const CHAR* source, FwSizeType buffer_size) {
33 22434602 FwSizeType length = 0;
34 22434602 FW_ASSERT(source != nullptr);
35
2/2
✓ Branch 0 taken 43962374 times.
✓ Branch 1 taken 3711 times.
43966085 for (length = 0; length < buffer_size; length++) {
36
2/2
✓ Branch 2 taken 22430891 times.
✓ Branch 3 taken 21531483 times.
43962374 if (source[length] == '\0') {
37 22430891 break;
38 }
39 }
40 22434602 return length;
41 }
42
43 4059 FwSignedSizeType Fw::StringUtils::substring_find(const CHAR* source_string,
44 FwSizeType source_size,
45 const CHAR* sub_string,
46 FwSizeType sub_size) {
47 4059 FW_ASSERT(source_string != nullptr);
48 4059 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 4057 times.
4059 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 4056 times.
4057 if (source_size < sub_size) {
57 1 return -1;
58 }
59 // Confirm that the output type can hold the range of valid results
60 4056 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 6924 for (FwSizeType source_index = 0;
64
4/4
✓ Branch 0 taken 5537 times.
✓ Branch 1 taken 1387 times.
✓ Branch 2 taken 5537 times.
✓ Branch 3 taken 1387 times.
12461 source_index < (source_size - sub_size + 1) &&
65
1/2
✓ Branch 1 taken 5537 times.
✗ Branch 2 not taken.
5537 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 75950 times.
✗ Branch 1 not taken.
75950 for (FwSizeType sub_index = 0; sub_index < sub_size; sub_index++) {
69 // Prevent read overrun
70 75950 FW_ASSERT((source_index + sub_index) < source_size);
71 // if there is a mismatch, go to next character
72
2/2
✓ Branch 4 taken 2868 times.
✓ Branch 5 taken 73082 times.
75950 if (source_string[source_index + sub_index] != sub_string[sub_index]) {
73 2868 break;
74
2/2
✓ Branch 0 taken 2669 times.
✓ Branch 1 taken 70413 times.
73082 } else if (sub_index == (sub_size - 1)) {
75 // if we matched all the way to the end of the substring
76 2669 return static_cast<FwSignedSizeType>(source_index);
77 }
78 }
79 }
80
81 // if we make it here, no matches were found
82 1387 return -1;
83 }
84
85 6345 FwSignedSizeType Fw::StringUtils::substring_find_last(const CHAR* source_string,
86 FwSizeType source_size,
87 const CHAR* sub_string,
88 FwSizeType sub_size) {
89 6345 FW_ASSERT(source_string != nullptr);
90 6345 FW_ASSERT(sub_string != nullptr);
91
92 6345 FwSizeType match_index = 0;
93
94 // zero size sub-strings should always match
95
4/4
✓ Branch 0 taken 6344 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6343 times.
6345 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 6343 times.
6344 if (source_size < sub_size) {
106 1 return -1;
107 }
108 // Confirm that the output type can hold the range of valid results
109 6343 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 6343 const FwSizeType max_start_index = source_size - sub_size;
113
2/2
✓ Branch 0 taken 95970 times.
✓ Branch 1 taken 322 times.
96292 for (FwSizeType ii = 0; ii <= max_start_index; ii++) {
114 95970 const FwSizeType source_index = max_start_index - ii;
115
116 // if the current character matches
117
1/2
✓ Branch 0 taken 107369 times.
✗ Branch 1 not taken.
107369 for (FwSizeType sub_index = 0; sub_index < sub_size; sub_index++) {
118 // Prevent read overrun
119 107369 FW_ASSERT((source_index + sub_index) < source_size);
120 // if there is a mismatch, go to next character
121
2/2
✓ Branch 4 taken 89949 times.
✓ Branch 5 taken 17420 times.
107369 if (source_string[source_index + sub_index] != sub_string[sub_index]) {
122 89949 break;
123
2/2
✓ Branch 0 taken 6021 times.
✓ Branch 1 taken 11399 times.
17420 } else if (sub_index == (sub_size - 1)) {
124 // if we matched all the way to the end of the substring
125 6021 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 6021 return static_cast<FwSignedSizeType>(match_index);
131 }
132 }
133 }
134
135 // if we make it here, no matches were found
136 322 return -1;
137 }
138