GCC Code Coverage Report


Directory: ./
File: firmware/util/efilib.cpp
Date: 2025-10-03 00:57:22
Warnings: 1 unchecked decisions!
Coverage Exec Excl Total
Lines: 75.9% 88 0 116
Functions: 88.9% 16 0 18
Branches: 67.7% 42 0 62
Decisions: 58.1% 18 - 31

Line Branch Decision Exec Source
1 /**
2 * @file efilib.cpp
3 *
4 * We cannot use stdlib because we do not have malloc - so, we have to implement these functions
5 *
6 * @date Feb 21, 2014
7 * @author Andrey Belomutskiy, (c) 2012-2020
8 */
9
10 #include "pch.h"
11
12 #include <cstring>
13 #include <cctype>
14 #include <cmath>
15 #include "datalogging.h"
16 #include "histogram.h"
17
18 // also known as bool2string and boolean2string
19 196078 const char * boolToString(bool value) {
20
2/2
✓ Branch 0 taken 5031 times.
✓ Branch 1 taken 191047 times.
196078 return value ? "Yes" : "No";
21 }
22
23 /*
24 float efiFloor(float value, float precision) {
25 int a = (int) (value / precision);
26 return a * precision;
27 }
28 */
29
30 /**
31 *
32 * @param precision for example '0.1' for one digit fractional part
33 */
34 657497 float efiRound(float value, float precision) {
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 657497 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 657497 times.
657497 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, precision != 0, "Zero precision is not valid for efiRound maybe you mean '1'?", NAN);
36 657497 float a = round(value / precision);
37
4/4
✓ Branch 0 taken 5295 times.
✓ Branch 1 taken 652202 times.
✓ Branch 2 taken 5293 times.
✓ Branch 3 taken 2 times.
657497 return fixNegativeZero(a * precision);
38 }
39
40 1 char * efiTrim(char *param) {
41
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 time.
3 while (param[0] == ' ') {
42 2 param++; // that would skip leading spaces
43 }
44 1 int len = std::strlen(param);
45
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
0/1
? Decision couldn't be analyzed.
3 while (len > 0 && param[len - 1] == ' ') {
46 2 param[len - 1] = 0;
47 2 len--;
48 }
49 1 return param;
50 }
51
52 95297 static char *ltoa_internal(char *p, uint32_t num, unsigned radix) {
53 95297 constexpr int bufferLength = 10;
54
55 95297 char buffer[bufferLength];
56
57 95297 size_t idx = bufferLength - 1;
58
59 // First, we write from right-to-left so that we don't have to compute
60 // log(num)/log(radix)
61 do
62 {
63 275603 auto digit = num % radix;
64
65 // Digits 0-9 -> '0'-'9'
66 // Digits 10-15 -> 'a'-'f'
67
1/2
✓ Branch 0 taken 275603 times.
✗ Branch 1 not taken.
275603 char c = digit < 10
68 275603 ? digit + '0'
69 : digit + 'a' - 10;
70
71 // Write this digit in to the buffer
72 275603 buffer[idx] = c;
73 275603 idx--;
74
2/2
✓ Branch 0 taken 180306 times.
✓ Branch 1 taken 95297 times.
2/2
✓ Decision 'true' taken 180306 times.
✓ Decision 'false' taken 95297 times.
275603 } while ((num /= radix) != 0);
75
76 95297 idx++;
77
78 // Now, we copy characters in to place in the final buffer
79
2/2
✓ Branch 0 taken 275603 times.
✓ Branch 1 taken 95297 times.
2/2
✓ Decision 'true' taken 275603 times.
✓ Decision 'false' taken 95297 times.
370900 while (idx < bufferLength)
80 {
81 275603 *p++ = buffer[idx++];
82 }
83
84 95297 return p;
85 }
86
87 /**
88 * @return pointer at the end zero symbol after the digits
89 */
90 95297 static char* itoa_signed(char *p, int num, unsigned radix) {
91
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95297 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 95297 times.
95297 if (num < 0) {
92 *p++ = '-';
93 char *end = ltoa_internal(p, -num, radix);
94 *end = 0;
95 return end;
96 }
97 95297 char *end = ltoa_internal(p, num, radix);
98 95297 *end = 0;
99 95297 return end;
100 }
101
102 /**
103 * Integer to string
104 *
105 * @return pointer at the end zero symbol after the digits
106 */
107 95297 char* itoa10(char *p, int num) {
108 95297 return itoa_signed(p, num, 10);
109 }
110
111 int efiPow10(int param) {
112 switch (param) {
113 case 0:
114 return 1;
115 case 1:
116 return 10;
117 case 2:
118 return 100;
119 case 3:
120 return 1000;
121 case 4:
122 return 10000;
123 case 5:
124 return 100000;
125 case 6:
126 return 1000000;
127 case 7:
128 return 10000000;
129 case 8:
130 return 100000000;
131 }
132 return 10 * efiPow10(10 - 1);
133 }
134
135 16 int djb2lowerCase(const char *str) {
136 16 unsigned long hash = 5381;
137 int c;
138
139
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 16 times.
2/2
✓ Decision 'true' taken 209 times.
✓ Decision 'false' taken 16 times.
225 while ( (c = *str++) ) {
140 209 c = std::tolower(c);
141 209 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
142 }
143
144 16 return hash;
145 }
146
147 /**
148 * @brief This function knows how to print a histogram_s summary
149 */
150 void printHistogram(Logging *logging, histogram_s *histogram) {
151 #if EFI_HISTOGRAMS && ! EFI_UNIT_TEST
152 int report[5];
153 int len = hsReport(histogram, report);
154
155 logging->reset();
156 logging.append(PROTOCOL_MSG LOG_DELIMITER);
157 logging.appendPrintf("histogram %s *", histogram->name);
158 for (int i = 0; i < len; i++)
159 logging.appendPrintf("%d ", report[i]);
160 logging.appendPrintf("*");
161 logging.append(LOG_DELIMITER);
162 scheduleLogging(logging);
163 #else
164 UNUSED(logging);
165 UNUSED(histogram);
166
167 #endif /* EFI_HISTOGRAMS */
168 }
169
170 912 float limitRateOfChange(float newValue, float oldValue, float incrLimitPerSec, float decrLimitPerSec, float secsPassed) {
171
2/2
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 11 times.
2/2
✓ Decision 'true' taken 901 times.
✓ Decision 'false' taken 11 times.
912 if (newValue >= oldValue)
172
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 901 times.
✓ Branch 5 taken 901 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 901 times.
✗ Branch 9 not taken.
901 return (incrLimitPerSec <= 0.0f) ? newValue : oldValue + std::min(newValue - oldValue, incrLimitPerSec * secsPassed);
173
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
11 return (decrLimitPerSec <= 0.0f) ? newValue : oldValue - std::min(oldValue - newValue, decrLimitPerSec * secsPassed);
174 }
175
176 245865 bool isPhaseInRange(float test, float current, float next) {
177 245865 bool afterCurrent = test >= current;
178 245865 bool beforeNext = test < next;
179
180
2/2
✓ Branch 0 taken 226142 times.
✓ Branch 1 taken 19723 times.
2/2
✓ Decision 'true' taken 226142 times.
✓ Decision 'false' taken 19723 times.
245865 if (next > current) {
181 // we're not near the end of the cycle, comparison is simple
182 // 0 |------------------------| 720
183 // next current
184
4/4
✓ Branch 0 taken 145150 times.
✓ Branch 1 taken 80992 times.
✓ Branch 2 taken 19439 times.
✓ Branch 3 taken 125711 times.
226142 return afterCurrent && beforeNext;
185 } else {
186 // we're near the end of the cycle so we have to check the wraparound
187 // 0 -----------| |------ 720
188 // next current
189 // Check whether test is after current (ie, between current tooth and end of cycle)
190 // or if test if before next (ie, between start of cycle and next tooth)
191
4/4
✓ Branch 0 taken 12851 times.
✓ Branch 1 taken 6872 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12849 times.
19723 return afterCurrent || beforeNext;
192 }
193 }
194
195 43 static int getBitRangeCommon(const uint8_t data[], int bitIndex, int bitWidth, int secondByteOffset) {
196 43 int byteIndex = bitIndex >> 3;
197 43 int shift = bitIndex - byteIndex * 8;
198 43 int value = data[byteIndex];
199
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 12 times.
2/2
✓ Decision 'true' taken 31 times.
✓ Decision 'false' taken 12 times.
43 if (shift + bitWidth > 8) {
200 31 value = value + data[secondByteOffset + byteIndex] * 256;
201 }
202 43 int mask = (1 << bitWidth) - 1;
203 43 return (value >> shift) & mask;
204 }
205
206 // see also getBitRange in lua_lib.h
207 5 int getBitRangeLsb(const uint8_t data[], int bitIndex, int bitWidth) {
208 5 return getBitRangeCommon(data, bitIndex, bitWidth, 1);
209 }
210
211 // see also getBitRangeMsb in lua_lib.h
212 38 int getBitRangeMsb(const uint8_t data[], int bitIndex, int bitWidth) {
213 38 return getBitRangeCommon(data, bitIndex, bitWidth, -1);
214 }
215
216 23 void setBitRangeMsb(uint8_t data[], const int totalBitIndex, const int bitWidth, const int value) {
217 23 int leftBitWidh = bitWidth;
218 23 const int byteIndex = totalBitIndex >> 3;
219 23 const int bitInByteIndex = totalBitIndex - byteIndex * 8;
220
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
2/2
✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 13 times.
23 if (bitInByteIndex + leftBitWidh > 8) {
221 10 const int bitsToHandleNow = 8 - bitInByteIndex;
222 10 setBitRangeMsb(data, (byteIndex - 1) * 8, leftBitWidh - bitsToHandleNow, value >> bitsToHandleNow);
223 10 leftBitWidh = bitsToHandleNow;
224 }
225 23 const int mask = (1 << leftBitWidh) - 1;
226 23 data[byteIndex] = data[byteIndex] & (~(mask << bitInByteIndex));
227 23 const int maskedValue = value & mask;
228 23 const int shiftedValue = maskedValue << bitInByteIndex;
229 23 data[byteIndex] = data[byteIndex] | shiftedValue;
230 23 }
231
232 46 int motorolaMagicFromDbc(int b, int length) {
233 // https://github.com/ebroecker/canmatrix/wiki/signal-Byteorder
234 // convert from lsb0 bit numbering to msb0 bit numbering (or msb0 to lsb0)
235 46 b = b - (b % 8) + 7 - (b % 8);
236 // convert from lsbit of signal data to msbit of signal data, when bit numbering is msb0
237 46 b = b + length - 1;
238 // convert from msbit of signal data to lsbit of signal data, when bit numbering is msb0
239 46 b = b - (b % 8) + 7 - (b % 8);
240 46 return b;
241 }
242
243 20 int getBitRangeMoto(const uint8_t data[], int bitIndex, int bitWidth) {
244 20 const int b = motorolaMagicFromDbc(bitIndex, bitWidth);
245 20 return getBitRangeMsb(data, b, bitWidth);
246 }
247
248 10 void setBitRangeMoto(uint8_t data[], const int totalBitIndex, const int bitWidth, const int value) {
249 10 const int b = motorolaMagicFromDbc(totalBitIndex, bitWidth);
250 10 return setBitRangeMsb(data, b, bitWidth, value);
251 }
252