GCC Code Coverage Report


Directory: ./
File: Fw/Types/StringUtils.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 16 60 26.7%
Functions: 2 5 40.0%
Branches: 6 40 15.0%

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 2084 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 2084 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2084 times.
2084 if (destination == source || num == 0) {
10 return destination;
11 }
12 2084 FW_ASSERT(source != nullptr);
13 2084 FW_ASSERT(destination != nullptr);
14
15 // Copying an overlapping range is undefined
16 2084 FwSizeType source_len = string_length(source, num) + 1;
17 2084 FW_ASSERT(source + source_len <= destination || destination + num <= source);
18
19 2083 char* returned = strncpy(destination, source, static_cast<size_t>(num));
20 2083 destination[num - 1] = '\0';
21 2083 return returned;
22 }
23
24 const char* Fw::StringUtils::string_last_n(const char* source, const FwSizeType n, const FwSizeType buffer_size) {
25 FW_ASSERT(source != nullptr);
26 FwSizeType length = Fw::StringUtils::string_length(source, buffer_size);
27
28 // Calculate start index. If string is shorter than N, keep whole string.
29 return (length > n) ? source + (length - n) : source;
30 }
31
32 11309 FwSizeType Fw::StringUtils::string_length(const CHAR* source, FwSizeType buffer_size) {
33 11309 FwSizeType length = 0;
34 11309 FW_ASSERT(source != nullptr);
35
2/2
✓ Branch 0 taken 270205 times.
✓ Branch 1 taken 25 times.
270230 for (length = 0; length < buffer_size; length++) {
36
2/2
✓ Branch 0 taken 11284 times.
✓ Branch 1 taken 258921 times.
270205 if (source[length] == '\0') {
37 11284 break;
38 }
39 }
40 11309 return length;
41 }
42
43 FwSignedSizeType Fw::StringUtils::substring_find(const CHAR* source_string,
44 FwSizeType source_size,
45 const CHAR* sub_string,
46 FwSizeType sub_size) {
47 FW_ASSERT(source_string != nullptr);
48 FW_ASSERT(sub_string != nullptr);
49
50 // zero size sub-strings should always match, including in an empty source
51 if (0 == sub_size) {
52 return 0;
53 }
54
55 // Cannot find a substring larger than the source
56 if (source_size < sub_size) {
57 return -1;
58 }
59 // Confirm that the output type can hold the range of valid results
60 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 for (FwSizeType source_index = 0;
64 source_index < (source_size - sub_size + 1) &&
65 source_index < static_cast<FwSizeType>(std::numeric_limits<FwSignedSizeType>::max());
66 source_index++) {
67 // if the current character matches
68 for (FwSizeType sub_index = 0; sub_index < sub_size; sub_index++) {
69 // Prevent read overrun
70 FW_ASSERT((source_index + sub_index) < source_size);
71 // if there is a mismatch, go to next character
72 if (source_string[source_index + sub_index] != sub_string[sub_index]) {
73 break;
74 } else if (sub_index == (sub_size - 1)) {
75 // if we matched all the way to the end of the substring
76 return static_cast<FwSignedSizeType>(source_index);
77 }
78 }
79 }
80
81 // if we make it here, no matches were found
82 return -1;
83 }
84
85 FwSignedSizeType Fw::StringUtils::substring_find_last(const CHAR* source_string,
86 FwSizeType source_size,
87 const CHAR* sub_string,
88 FwSizeType sub_size) {
89 FW_ASSERT(source_string != nullptr);
90 FW_ASSERT(sub_string != nullptr);
91
92 FwSizeType match_index = 0;
93
94 // zero size sub-strings should always match
95 if ((source_size > 0) && (0 == sub_size)) {
96 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 return static_cast<FwSignedSizeType>(match_index);
102 }
103
104 // Cannot find a substring larger than the source
105 if (source_size < sub_size) {
106 return -1;
107 }
108 // Confirm that the output type can hold the range of valid results
109 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 const FwSizeType max_start_index = source_size - sub_size;
113 for (FwSizeType ii = 0; ii <= max_start_index; ii++) {
114 const FwSizeType source_index = max_start_index - ii;
115
116 // if the current character matches
117 for (FwSizeType sub_index = 0; sub_index < sub_size; sub_index++) {
118 // Prevent read overrun
119 FW_ASSERT((source_index + sub_index) < source_size);
120 // if there is a mismatch, go to next character
121 if (source_string[source_index + sub_index] != sub_string[sub_index]) {
122 break;
123 } else if (sub_index == (sub_size - 1)) {
124 // if we matched all the way to the end of the substring
125 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 return static_cast<FwSignedSizeType>(match_index);
131 }
132 }
133 }
134
135 // if we make it here, no matches were found
136 return -1;
137 }
138