GCC Code Coverage Report


Directory: ./
File: Fw/Types/StringToNumber.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 27 65 41.5%
Functions: 4 20 20.0%
Branches: 13 35 37.1%

Line Branch Exec Source
1 #include <Fw/Types/StringUtils.hpp>
2 #include <cerrno>
3 #include <cstdlib>
4
5 96 Fw::StringUtils::StringToNumberStatus string_to_helper_input_check(const CHAR* input, FwSizeType buffer_size, U8 base) {
6 96 Fw::StringUtils::StringToNumberStatus status = Fw::StringUtils::StringToNumberStatus::SUCCESSFUL_CONVERSION;
7 // Check for null input string
8
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (input == nullptr) {
9 status = Fw::StringUtils::NULL_INPUT;
10 }
11 // Invalid base e.g. not 0, 2-36
12
2/4
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 96 times.
96 else if (base == 1 || base > 36) {
13 status = Fw::StringUtils::INVALID_BASE;
14 } else {
15 // Check the string is bounded within the specified length
16 96 FwSizeType length = Fw::StringUtils::string_length(input, buffer_size);
17
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (length == buffer_size) {
18 status = Fw::StringUtils::INVALID_STRING;
19 }
20 }
21 96 errno = 0;
22 96 return status;
23 }
24
25 96 Fw::StringUtils::StringToNumberStatus string_to_helper_output_check(Fw::StringUtils::StringToNumberStatus status,
26 const char* original_input,
27 char*& internal_next,
28 char** external_next) {
29 // Check range, if error then
30
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
96 if (errno == ERANGE) {
31 status = Fw::StringUtils::INVALID_RANGE;
32 }
33 // Invalid number conversion
34
2/4
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 96 times.
96 else if ((internal_next == original_input) || (internal_next == nullptr)) {
35 internal_next = nullptr;
36 status = Fw::StringUtils::INVALID_NUMBER;
37 }
38 // Set output pointer in all cases
39
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (external_next != nullptr) {
40 96 *external_next = internal_next;
41 }
42 96 errno = 0;
43 96 return status;
44 }
45
46 // Template for internal implementation only
47 // \tparam T: input type (U8, I8, U64, I64)
48 // \tparam Tinternal: function api type
49 // \tparam F: conversion function to use
50 template <typename T, typename Tinternal, Tinternal (*F)(const char*, char**, int)>
51 192 Fw::StringUtils::StringToNumberStatus string_to_number_as_template(const CHAR* input,
52 FwSizeType buffer_size,
53 T& output,
54 char** next,
55 U8 base) {
56 static_assert(std::numeric_limits<T>::is_integer, "Type must be integer");
57 static_assert(std::numeric_limits<Tinternal>::is_integer, "Type must be integer");
58 static_assert(std::numeric_limits<T>::is_signed == std::numeric_limits<Tinternal>::is_signed,
59 "Signedness must match");
60 static_assert(std::numeric_limits<T>::max() <= std::numeric_limits<Tinternal>::max(),
61 "Invalid internal type chosen");
62 static_assert(std::numeric_limits<T>::min() >= std::numeric_limits<Tinternal>::min(),
63 "Invalid internal type chosen");
64
65 192 char* output_next = nullptr;
66
1/1
✓ Branch 1 taken 96 times.
192 Fw::StringUtils::StringToNumberStatus status = string_to_helper_input_check(input, buffer_size, base);
67
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
192 if (status == Fw::StringUtils::SUCCESSFUL_CONVERSION) {
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
192 Tinternal output_api = F(input, &output_next, base);
69
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
192 if (output_api > std::numeric_limits<T>::max()) {
70 status = Fw::StringUtils::StringToNumberStatus::INVALID_RANGE;
71 output_api = std::numeric_limits<T>::max();
72 }
73
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
192 if (output_api < std::numeric_limits<T>::min()) {
74 status = Fw::StringUtils::StringToNumberStatus::INVALID_RANGE;
75 output_api = std::numeric_limits<T>::min();
76 }
77 192 output = static_cast<T>(output_api);
78 }
79 192 status = string_to_helper_output_check(status, input, output_next, next);
80 192 return status;
81 }
82
83 #if FW_HAS_64_BIT
84 96 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
85 FwSizeType buffer_size,
86 U64& output,
87 char** next,
88 U8 base) {
89 96 return string_to_number_as_template<U64, unsigned long long, strtoull>(input, buffer_size, output, next, base);
90 }
91
92 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
93 FwSizeType buffer_size,
94 I64& output,
95 char** next,
96 U8 base) {
97 return string_to_number_as_template<I64, long long, strtoll>(input, buffer_size, output, next, base);
98 }
99 #endif
100 #if FW_HAS_32_BIT
101 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
102 FwSizeType buffer_size,
103 U32& output,
104 char** next,
105 U8 base) {
106 return string_to_number_as_template<U32, unsigned long long, strtoull>(input, buffer_size, output, next, base);
107 }
108
109 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
110 FwSizeType buffer_size,
111 I32& output,
112 char** next,
113 U8 base) {
114 return string_to_number_as_template<I32, long long, strtoll>(input, buffer_size, output, next, base);
115 }
116 #endif
117 #if FW_HAS_16_BIT
118 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
119 FwSizeType buffer_size,
120 U16& output,
121 char** next,
122 U8 base) {
123 return string_to_number_as_template<U16, unsigned long long, strtoull>(input, buffer_size, output, next, base);
124 }
125 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
126 FwSizeType buffer_size,
127 I16& output,
128 char** next,
129 U8 base) {
130 return string_to_number_as_template<I16, long long, strtoll>(input, buffer_size, output, next, base);
131 }
132 #endif
133 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
134 FwSizeType buffer_size,
135 U8& output,
136 char** next,
137 U8 base) {
138 return string_to_number_as_template<U8, unsigned long long, strtoull>(input, buffer_size, output, next, base);
139 }
140 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
141 FwSizeType buffer_size,
142 I8& output,
143 char** next,
144 U8 base) {
145 return string_to_number_as_template<I8, long long, strtoll>(input, buffer_size, output, next, base);
146 }
147 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
148 FwSizeType buffer_size,
149 F64& output,
150 char** next) {
151 char* output_next = nullptr;
152 Fw::StringUtils::StringToNumberStatus status = string_to_helper_input_check(input, buffer_size, 0);
153 if (status == SUCCESSFUL_CONVERSION) {
154 output = strtod(input, &output_next);
155 }
156 status = string_to_helper_output_check(status, input, output_next, next);
157 return status;
158 }
159
160 Fw::StringUtils::StringToNumberStatus Fw::StringUtils::string_to_number(const CHAR* input,
161 FwSizeType buffer_size,
162 F32& output,
163 char** next) {
164 char* output_next = nullptr;
165 Fw::StringUtils::StringToNumberStatus status = string_to_helper_input_check(input, buffer_size, 0);
166 if (status == SUCCESSFUL_CONVERSION) {
167 output = strtof(input, &output_next);
168 }
169 status = string_to_helper_output_check(status, input, output_next, next);
170 return status;
171 }
172