Aruna
log.cpp
Go to the documentation of this file.
1 //
2 // Created by noeel on 17-7-19.
3 //
4 
5 #include <cstdio>
6 #include <cstdint>
7 #include <stdarg.h>
8 #include <cstring>
9 #include <aruna.h>
10 #include "aruna/log.h"
11 #include "set"
12 
13 #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
14 
15 #include "time.h"
16 
17 #elif defined(ESP_PLATFORM)
18 #include "esp_log.h"
19 #endif
20 namespace aruna {
21  namespace log {
22 // private
23 // variables
24  std::set<channel_t*>* channels() {
25 // mitigate Static Initialization Order Fiasco
26  static std::set<channel_t*> channels;
27  return &channels;
28  }
31 
32 // functions
33  int register_channel(channel_t *channel);
34 
35 // public
36 
37  // functions
38  int channel_t::verbose(const char *format, ...) {
39  char buffer[256];
40  int n = 0;
41  va_list argptr;
42 
43  va_start(argptr, format);
44  vsprintf(buffer, format, argptr);
45  n = print(level_t::VERBOSE, buffer);
46  va_end(argptr);
47 
48  return n;
49  }
50 
51  int channel_t::debug(const char *format, ...) {
52  char buffer[256];
53  int n = 0;
54  va_list argptr;
55 
56  va_start(argptr, format);
57  vsprintf(buffer, format, argptr);
58  n = print(level_t::DEBUG, buffer);
59  va_end(argptr);
60 
61  return n;
62  }
63 
64  int channel_t::info(const char *format, ...) {
65  char buffer[256];
66  int n = 0;
67  va_list argptr;
68 
69  va_start(argptr, format);
70  vsprintf(buffer, format, argptr);
71  n = print(level_t::INFO, buffer);
72  va_end(argptr);
73 
74  return n;
75  }
76 
77  int channel_t::warning(const char *format, ...) {
78  char buffer[256];
79  int n = 0;
80  va_list argptr;
81 
82  va_start(argptr, format);
83  vsprintf(buffer, format, argptr);
84  n = print(level_t::WARNING, buffer);
85  va_end(argptr);
86 
87  return n;
88  }
89 
90  int channel_t::error(const char *format, ...) {
91  char buffer[256];
92  int n = 0;
93  va_list argptr;
94 
95  va_start(argptr, format);
96  vsprintf(buffer, format, argptr);
97  n = print(level_t::ERROR, buffer);
98  va_end(argptr);
99 
100  return n;
101  }
102 
103  int channel_t::print(level_t level, const char *format) {
104  char level_txt[5];
105  if (((int) level > (int) this->level) || ((int) level > (int) max_level) || level == level_t::NONE) {
106  return 0;
107  }
108  level_t_to_char(level, level_txt);
109  return out("%s (%u) %s, %s\n", level_txt, epoch(), name, format);
110  }
111 
112  channel_t::channel_t(const char *name, level_t level) : name(name), level(level) {
114  if (!register_channel(this))
116  }
117 
118  unsigned long channel_t::epoch() {
119 #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
120  return ::time(NULL);
121 #elif defined(ESP_PLATFORM)
122  return esp_log_timestamp();
123 #endif
124  }
125 
126  int channel_t::out(const char *format, ...) {
127  va_list list;
128  int n;
129  va_start(list, format);
130  n = print_function(format, list);
131  va_end(list);
132  return n;
133  }
134 
135  int channel_t::dump(level_t level, uint8_t *bin, size_t size) {
136 // TODO this if statement is copied two times, there should be a function that implements it
137  if (((int) level > (int) this->level) || ((int) level > (int) max_level) || level == level_t::NONE) {
138  return 0;
139  }
140 #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
141  char level_c[5];
142  level_t_to_char(level, level_c);
143 // TODO formatting should be staderlized
144  out("%s (%u) %s, 0x%X ", level_c, epoch(), name, bin);
145  for (int i = 0; i < size ; ++i) {
146  out("%02X ", bin[i]);
147  }
148  out("\n");
149  return size;
150 #elif defined(ESP_PLATFORM)
151  esp_log_level_t esp_log_level;
152  switch (level) {
153  case level_t::VERBOSE:
154  esp_log_level = ESP_LOG_VERBOSE;
155  break;
156  case level_t::DEBUG:
157  esp_log_level = ESP_LOG_DEBUG;
158  break;
159  case level_t::INFO:
160  esp_log_level = ESP_LOG_INFO;
161  break;
162  case level_t::WARNING:
163  esp_log_level = ESP_LOG_WARN;
164  break;
165  case level_t::ERROR:
166  esp_log_level = ESP_LOG_ERROR;
167  break;
168  default:
169  case log::level_t::NONE:
170  esp_log_level = ESP_LOG_NONE;
171  break;
172  }
173  ESP_LOG_BUFFER_HEXDUMP(name, bin, size, esp_log_level);
174  return size;
175 #endif
176  }
177 
179  channels()->erase(this);
180  }
181 
182  int register_channel(channel_t *channel) {
183  for (auto candidate: *channels()) {
184  if (!strcmp(candidate->name, channel->name)) {
185  return 0;
186  }
187  }
188  return channels()->insert(channel).second;
189  }
190 
191  int set_level(const char *channel_name, level_t new_level) {
192 // TODO set level on channel instead of log manager
193  int success = false;
194  for (auto candidate: *channels()) {
195  if (!strcmp(candidate->name, channel_name)) {
196  success = true;
197  candidate->level = new_level;
198  }
199  }
200  return success;
201  }
202 
204  vprintf_like_t old_func = print_function;
205  print_function = func;
206  return old_func;
207  }
208 
210  level_t old_max_level = max_level;
211  max_level = level;
212  return old_max_level;
213  }
214 
215  void level_t_to_char(level_t level, char *buffer) {
216  switch (level) {
217  case log::level_t::NONE:
218  strcpy(buffer, "NONE ");
219  break;
220  case level_t::VERBOSE:
221  strcpy(buffer, "VERBO");
222  break;
223  case level_t::DEBUG:
224  strcpy(buffer, "DEBUG");
225  break;
226  case level_t::INFO:
227  strcpy(buffer, "INFO ");
228  break;
229  case level_t::WARNING:
230  strcpy(buffer, "WARN ");
231  break;
232  case level_t::ERROR:
233  strcpy(buffer, "ERROR");
234  break;
235  default:
236  strcpy(buffer, "lvler");
237  break;
238  }
239  }
240  }
241 }
Definition: comm.cpp:14
int debug(const char *format,...)
log debug message
Definition: log.cpp:51
vprintf_like_t set_print_function(vprintf_like_t func)
Set a new print function to log to a diffrent location.
Definition: log.cpp:203
const char * name
Channel name, used to identify.
Definition: log.h:29
static log::channel_t * log
Definition: comm.cpp:23
std::set< channel_t * > * channels()
Definition: log.cpp:24
level_t set_max_level(level_t level)
set maximum print level for all channels
Definition: log.cpp:209
unsigned long epoch()
Definition: log.cpp:118
err_t startup_status
Contains the error happens at construction.
Definition: log.h:43
channel_t(const char *name, level_t level=default_level)
Definition: log.cpp:112
level_t max_level
Definition: log.cpp:29
int(* vprintf_like_t)(const char *, va_list)
Definition: log.h:21
int register_channel(channel_t *channel)
Definition: log.cpp:182
level_t level
max log level of channel
Definition: log.h:34
vprintf_like_t print_function
Definition: log.cpp:30
int verbose(const char *format,...)
log verbose message
Definition: log.cpp:38
int set_level(const char *channel_name, level_t new_level)
Set level of log channel.
Definition: log.cpp:191
void level_t_to_char(level_t level, char *buffer)
convert level_t object to char
Definition: log.cpp:215
int out(const char *format,...)
Definition: log.cpp:126
int print(level_t level, const char *format)
Definition: log.cpp:103
int warning(const char *format,...)
log warning message
Definition: log.cpp:77
int error(const char *format,...)
log error message
Definition: log.cpp:90
level_t
Definition: log.h:13
int info(const char *format,...)
log info message
Definition: log.cpp:64
int dump(level_t level, uint8_t *bin, size_t size)
dump array of bin data
Definition: log.cpp:135