1 /**
2 @file Logger.cpp
3 @author Lime Microsystems
4 @brief API for reporting error codes and error messages.
5 */
6 
7 #include "Logger.h"
8 #include <cstdio>
9 #include <cstring> //strerror
10 
11 
12 #ifdef _MSC_VER
13     #define thread_local __declspec( thread )
14     #include <Windows.h>
15 #endif
16 
17 #ifdef __APPLE__
18     #define thread_local __thread
19 #endif
20 
21 #define MAX_MSG_LEN 1024
22 thread_local int _reportedErrorCode;
23 thread_local char _reportedErrorMessage[MAX_MSG_LEN];
24 
errToStr(const int errnum)25 static const char *errToStr(const int errnum)
26 {
27     thread_local static char buff[MAX_MSG_LEN];
28     #ifdef _MSC_VER
29     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buff, sizeof(buff), NULL);
30     return buff;
31     #else
32     //http://linux.die.net/man/3/strerror_r
33     #if !(defined(__GLIBC__) && defined(__GNU_SOURCE))
34     strerror_r(errnum, buff, sizeof(buff));
35     #else
36     //this version may decide to use its own internal string
37     return strerror_r(errnum, buff, sizeof(buff));
38     #endif
39     return buff;
40     #endif
41 }
42 
GetLastErrorMessage(void)43 const char *lime::GetLastErrorMessage(void)
44 {
45     return _reportedErrorMessage;
46 }
47 
ReportError(const int errnum)48 int lime::ReportError(const int errnum)
49 {
50     return lime::ReportError(errnum, errToStr(errnum));
51 }
52 
ReportError(const int errnum,const char * format,va_list argList)53 int lime::ReportError(const int errnum, const char *format, va_list argList)
54 {
55     _reportedErrorCode = errnum;
56     vsnprintf(_reportedErrorMessage, MAX_MSG_LEN, format, argList);
57     lime::log(LOG_LEVEL_ERROR, _reportedErrorMessage);
58     return errnum;
59 }
60 
defaultLogHandler(const lime::LogLevel level,const char * message)61 static void defaultLogHandler(const lime::LogLevel level, const char *message)
62 {
63 #ifdef NDEBUG
64     if (level == lime::LOG_LEVEL_DEBUG)
65         return;
66 #endif
67     fprintf(stderr, "%s\n", message);
68 }
69 
70 static lime::LogHandler logHandler(&defaultLogHandler);
71 
log(const LogLevel level,const char * format,va_list argList)72 void lime::log(const LogLevel level, const char *format, va_list argList)
73 {
74     char buff[4096];
75     int ret = vsnprintf(buff, sizeof(buff), format, argList);
76     if (ret > 0) logHandler(level, buff);
77 }
78 
registerLogHandler(const LogHandler handler)79 void lime::registerLogHandler(const LogHandler handler)
80 {
81     logHandler = handler ? handler : defaultLogHandler;
82 }
83 
logLevelToName(const LogLevel level)84 const char *lime::logLevelToName(const LogLevel level)
85 {
86     switch(level)
87     {
88     case lime::LOG_LEVEL_CRITICAL: return "CRITICAL";
89     case lime::LOG_LEVEL_ERROR: return "ERROR";
90     case lime::LOG_LEVEL_WARNING: return "WARNING";
91     case lime::LOG_LEVEL_INFO: return "INFO";
92     case lime::LOG_LEVEL_DEBUG: return "DEBUG";
93     }
94     return "";
95 }
96