-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFF_Trace.cpp
123 lines (105 loc) · 3.24 KB
/
FF_Trace.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*!
\file
\brief Implements a centralized trace class
\author Flying Domotic
Have a look at FF_Trace.h for details.
Please prefer using macro in FF_Trace.h instead of calling class directly.
*/
#include "FF_Trace.h"
/*!
Class initialization
*/
FF_Trace::FF_Trace() {
// Clear all callbacks
for (uint8_t i = 0; i < FF_TRACE_MAX_TRACE; i++) {
callbacks[i] = NULL;
}
// Init level to info
currentLevel = FF_TRACE_LEVEL_INFO;
}
/*!
Register one callback to call when a message should be displayed
/param _callback: callback routine to be called when a message is to be displayed
*/
void FF_Trace::registerCallback(const traceCallback_t _callback) {
// Find an empty slot to insert callback
for (uint8_t i = 0; i < FF_TRACE_MAX_TRACE; i++) {
if (callbacks[i] == NULL) {
callbacks[i] = _callback;
return;
}
// No slot available, do nothing...
}
}
/*!
Send a message to all registered routines using printf format
A first try is done with a 200 bytes buffer.
If too short, a sufficiently long one is dynamically allocated.
IF dynamic allocation fails, only the first 200 bytes of message are displayed.
Else, full message is shown.
/param _level: level associated to this message
/param _file: calling source file name with extension
/param _line: calling source file line
/param _function: calling calling source function name
/param _format: (printf) format string to use
/param ...: associated parameters (depends on format string contents)
*/
void FF_Trace::printf(const traceLevel_t _level, const char* _file, const uint16_t _line, const char* _function, const char* _format, ...) {
// Check level against internal one
if (_level <= currentLevel) {
// Make the message
char msg[200]; // Allocate 200 bytes for message (larger buffer allocated dynamically if needed)
va_list arguments;
va_start(arguments, _format);
int size = vsnprintf(msg, sizeof(msg), _format, arguments);
va_end(arguments);
// Was buffer large enough?
if (size < (int) sizeof(msg)) {
// Call all registered callbacks
for (uint8_t i = 0; i < FF_TRACE_MAX_TRACE; i++) {
if (callbacks[i] != NULL) {
(callbacks[i])(_level, _file, _line, _function, msg);
}
}
} else {
// Use dynamic buffer allocation
char* buffer = (char *) malloc(size+1);
if (!buffer) {
// Not enougth memory, call all registered callbacks with fixed string
for (uint8_t i = 0; i < FF_TRACE_MAX_TRACE; i++) {
if (callbacks[i] != NULL) {
(callbacks[i])(_level, _file, _line, _function, msg);
}
}
} else {
va_list arguments;
va_start(arguments, _format);
vsnprintf(buffer, size, _format, arguments);
va_end(arguments);
// Call all registered callbacks with dynamic string
for (uint8_t i = 0; i < FF_TRACE_MAX_TRACE; i++) {
if (callbacks[i] != NULL) {
(callbacks[i])(_level, _file, _line, _function, buffer);
}
}
free(buffer);
}
}
}
}
/*!
Set current message level
/param _level: minimum level required to display message
*/
void FF_Trace::setLevel(const traceLevel_t _level) {
// Save given level
currentLevel = _level;
}
/*!
Return current message level
/return Current stored level
*/
traceLevel_t FF_Trace::getLevel(void) {
// Return internal level
return currentLevel;
}