GCC Code Coverage Report


Directory: ./
File: firmware/util/datalogging.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 38.3% 23 0 60
Functions: 50.0% 4 0 8
Branches: 17.6% 3 0 17
Decisions: 15.4% 2 - 13

Line Branch Decision Exec Source
1 /**
2 * @file datalogging.cpp
3 * @brief Buffered console output stream code
4 *
5 * Here we have a memory buffer and methods related to
6 * printing messages into this buffer. The purpose of the
7 * buffer is to allow fast, non-blocking, thread-safe logging.
8 *
9 * The idea is that each interrupt handler would have it's own logging buffer. You can add
10 * stuff into this buffer without any locking since it's you own buffer, and once you get
11 * the whole message you invoke the scheduleLogging() method which appends your local content
12 * into the global logging buffer, from which it is later dispatched to the console by our
13 * main console thread.
14 *
15 * @date Feb 25, 2013
16 * @author Andrey Belomutskiy, (c) 2012-2020
17 *
18 * This file is part of rusEfi - see http://rusefi.com
19 *
20 * rusEfi is free software; you can redistribute it and/or modify it under the terms of
21 * the GNU General Public License as published by the Free Software Foundation; either
22 * version 3 of the License, or (at your option) any later version.
23 *
24 * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
25 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License along with this program.
29 * If not, see <http://www.gnu.org/licenses/>.
30 *
31 */
32
33 #include "pch.h"
34
35 #if ! EFI_UNIT_TEST
36
37 #include "chmtx.h"
38 #include "memstreams.h"
39 #include "console_io.h"
40 #endif // EFI_UNIT_TEST
41
42 /**
43 * @returns true if data does not fit into this buffer
44 */
45 bool Logging::validateBuffer(uint32_t extraLen) {
46 if (remainingSize() < extraLen + 1) {
47 #if EFI_PROD_CODE
48 warning(ObdCode::CUSTOM_LOGGING_BUFFER_OVERFLOW, "output overflow %s %d", name, extraLen);
49 #endif /* EFI_PROD_CODE */
50 return true;
51 }
52
53 return false;
54 }
55
56 void Logging::append(const char *text) {
57 efiAssertVoid(ObdCode::CUSTOM_APPEND_NULL, text != NULL, "append NULL");
58 size_t extraLen = std::strlen(text);
59 bool isCapacityProblem = validateBuffer(extraLen);
60 if (isCapacityProblem) {
61 return;
62 }
63 strcpy(linePointer, text);
64 /**
65 * And now we are pointing at the zero char at the end of the buffer again
66 */
67 linePointer += extraLen;
68 }
69
70 /**
71 * @note This method if fast because it does not validate much, be sure what you are doing
72 */
73 79743 void Logging::appendFast(const char *text) {
74 79743 char *s = linePointer;
75
2/2
✓ Branch 0 taken 228761 times.
✓ Branch 1 taken 79743 times.
2/2
✓ Decision 'true' taken 228761 times.
✓ Decision 'false' taken 79743 times.
308504 while ((*s++ = *text++) != 0)
76 ;
77 79743 linePointer = s - 1;
78 79743 }
79
80 583 void Logging::appendPrintf(const char *fmt, ...) {
81 efiAssertVoid(ObdCode::CUSTOM_APPEND_STACK, hasLotsOfRemainingStack(), "lowstck#4");
82
83 583 size_t available = remainingSize();
84
85 583 va_list ap;
86 583 va_start(ap, fmt);
87 583 size_t written = chvsnprintf(linePointer, available, fmt, ap);
88 583 va_end(ap);
89
90 // chvnsprintf returns how many bytes WOULD HAVE been written if it fit,
91 // so clip it to the available space if necessary
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
583 linePointer += (written > available) ? available : written;
93 // ensure buffer is always null terminated
94 583 buffer[bufferSize - 1] = '\0';
95 }
96
97 void Logging::appendFloat(float value, int precision) {
98 /**
99 * todo: #1 this implementation is less than perfect
100 * todo: #2 The only way to avoid double promotion would probably be using *float instead of float
101 * See also http://stackoverflow.com/questions/5522051/printing-a-float-in-c-while-avoiding-variadic-parameter-promotion-to-double
102 */
103 switch (precision) {
104 case 1:
105 appendPrintf("%.1f", value);
106 break;
107 case 2:
108 appendPrintf("%.2f", value);
109 break;
110 case 3:
111 appendPrintf("%.3f", value);
112 break;
113 case 4:
114 appendPrintf("%.4f", value);
115 break;
116 case 5:
117 appendPrintf("%.5f", value);
118 break;
119 case 6:
120 appendPrintf("%.6f", value);
121 break;
122
123 default:
124 appendPrintf("%.2f", value);
125 }
126 }
127
128 584 void Logging::reset() {
129 584 linePointer = buffer;
130 584 *linePointer = 0;
131 584 }
132
133 1 Logging::Logging(char const *p_name, char *p_buffer, int p_bufferSize)
134 1 : name(p_name)
135 1 , buffer(p_buffer)
136 1 , bufferSize(p_bufferSize)
137 {
138 1 reset();
139 1 }
140
141 LoggingWithStorage::LoggingWithStorage(const char *p_name) : Logging(p_name, DEFAULT_BUFFER, sizeof(DEFAULT_BUFFER)) {
142 }
143