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