codekingpro/portable-devtools
114k
1/*
2 * This copyright notice applies to this header file only:
3 *
4 * Copyright (c) 2010-2024 NVIDIA Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the software, and to permit persons to whom the
12 * software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#pragma once
29
30#include <iostream>
31#include <fstream>
32#include <string>
33#include <sstream>
34#include <mutex>
35#include <time.h>
36
37#ifdef _WIN32
38#include <winsock.h>
39#include <windows.h>
40
41#pragma comment(lib, "ws2_32.lib")
42#undef ERROR
43#else
44#include <unistd.h>
45#include <sys/socket.h>
46#include <netinet/in.h>
47#include <arpa/inet.h>
48#define SOCKET int
49#define INVALID_SOCKET -1
50#endif
51
52enum LogLevel {
53 TRACE,
54 INFO,
55 WARNING,
56 ERROR,
57 FATAL
58};
59
60namespace simplelogger{
61class Logger {
62public:
63 Logger(LogLevel level, bool bPrintTimeStamp) : level(level), bPrintTimeStamp(bPrintTimeStamp) {}
64 virtual ~Logger() {}
65 virtual std::ostream& GetStream() = 0;
66 virtual void FlushStream() {}
67 bool ShouldLogFor(LogLevel l) {
68 return l >= level;
69 }
70 char* GetLead(LogLevel l, const char *szFile, int nLine, const char *szFunc) {
71 if (l < TRACE || l > FATAL) {
72 sprintf(szLead, "[?????] ");
73 return szLead;
74 }
75 const char *szLevels[] = {"TRACE", "INFO", "WARN", "ERROR", "FATAL"};
76 if (bPrintTimeStamp) {
77 time_t t = time(NULL);
78 struct tm *ptm = localtime(&t);
79 sprintf(szLead, "[%-5s][%02d:%02d:%02d] ",
80 szLevels[l], ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
81 } else {
82 sprintf(szLead, "[%-5s] ", szLevels[l]);
83 }
84 return szLead;
85 }
86 void EnterCriticalSection() {
87 mtx.lock();
88 }
89 void LeaveCriticalSection() {
90 mtx.unlock();
91 }
92private:
93 LogLevel level;
94 char szLead[80];
95 bool bPrintTimeStamp;
96 std::mutex mtx;
97};
98
99class LoggerFactory {
100public:
101 static Logger* CreateFileLogger(std::string strFilePath,
102 LogLevel level = INFO, bool bPrintTimeStamp = true) {
103 return new FileLogger(strFilePath, level, bPrintTimeStamp);
104 }
105 static Logger* CreateConsoleLogger(LogLevel level = INFO,
106 bool bPrintTimeStamp = true) {
107 return new ConsoleLogger(level, bPrintTimeStamp);
108 }
109 static Logger* CreateUdpLogger(char *szHost, unsigned uPort, LogLevel level = INFO,
110 bool bPrintTimeStamp = true) {
111 return new UdpLogger(szHost, uPort, level, bPrintTimeStamp);
112 }
113private:
114 LoggerFactory() {}
115
116 class FileLogger : public Logger {
117 public:
118 FileLogger(std::string strFilePath, LogLevel level, bool bPrintTimeStamp)
119 : Logger(level, bPrintTimeStamp) {
120 pFileOut = new std::ofstream();
121 pFileOut->open(strFilePath.c_str());
122 }
123 ~FileLogger() {
124 pFileOut->close();
125 }
126 std::ostream& GetStream() {
127 return *pFileOut;
128 }
129 private:
130 std::ofstream *pFileOut;
131 };
132
133 class ConsoleLogger : public Logger {
134 public:
135 ConsoleLogger(LogLevel level, bool bPrintTimeStamp)
136 : Logger(level, bPrintTimeStamp) {}
137 std::ostream& GetStream() {
138 return std::cout;
139 }
140 };
141
142 class UdpLogger : public Logger {
143 private:
144 class UdpOstream : public std::ostream {
145 public:
146 UdpOstream(char *szHost, unsigned short uPort) : std::ostream(&sb), socket(INVALID_SOCKET){
147#ifdef _WIN32
148 WSADATA w;
149 if (WSAStartup(0x0101, &w) != 0) {
150 fprintf(stderr, "WSAStartup() failed.\n");
151 return;
152 }
153#endif
154 socket = ::socket(AF_INET, SOCK_DGRAM, 0);
155 if (socket == INVALID_SOCKET) {
156#ifdef _WIN32
157 WSACleanup();
158#endif
159 fprintf(stderr, "socket() failed.\n");
160 return;
161 }
162#ifdef _WIN32
163 unsigned int b1, b2, b3, b4;
164 sscanf(szHost, "%u.%u.%u.%u", &b1, &b2, &b3, &b4);
165 struct in_addr addr = {(unsigned char)b1, (unsigned char)b2, (unsigned char)b3, (unsigned char)b4};
166#else
167 struct in_addr addr = {inet_addr(szHost)};
168#endif
169 struct sockaddr_in s = {AF_INET, htons(uPort), addr};
170 server = s;
171 }
172 ~UdpOstream() throw() {
173 if (socket == INVALID_SOCKET) {
174 return;
175 }
176#ifdef _WIN32
177 closesocket(socket);
178 WSACleanup();
179#else
180 close(socket);
181#endif
182 }
183 void Flush() {
184 if (sendto(socket, sb.str().c_str(), (int)sb.str().length() + 1,
185 0, (struct sockaddr *)&server, (int)sizeof(sockaddr_in)) == -1) {
186 fprintf(stderr, "sendto() failed.\n");
187 }
188 sb.str("");
189 }
190
191 private:
192 std::stringbuf sb;
193 SOCKET socket;
194 struct sockaddr_in server;
195 };
196 public:
197 UdpLogger(char *szHost, unsigned uPort, LogLevel level, bool bPrintTimeStamp)
198 : Logger(level, bPrintTimeStamp), udpOut(szHost, (unsigned short)uPort) {}
199 UdpOstream& GetStream() {
200 return udpOut;
201 }
202 virtual void FlushStream() {
203 udpOut.Flush();
204 }
205 private:
206 UdpOstream udpOut;
207 };
208};
209
210class LogTransaction {
211public:
212 LogTransaction(Logger *pLogger, LogLevel level, const char *szFile, const int nLine, const char *szFunc) : pLogger(pLogger), level(level) {
213 if (!pLogger) {
214 std::cout << "[-----] ";
215 return;
216 }
217 if (!pLogger->ShouldLogFor(level)) {
218 return;
219 }
220 pLogger->EnterCriticalSection();
221 pLogger->GetStream() << pLogger->GetLead(level, szFile, nLine, szFunc);
222 }
223 ~LogTransaction() {
224 if (!pLogger) {
225 std::cout << std::endl;
226 return;
227 }
228 if (!pLogger->ShouldLogFor(level)) {
229 return;
230 }
231 pLogger->GetStream() << std::endl;
232 pLogger->FlushStream();
233 pLogger->LeaveCriticalSection();
234 if (level == FATAL) {
235 exit(1);
236 }
237 }
238 std::ostream& GetStream() {
239 if (!pLogger) {
240 return std::cout;
241 }
242 if (!pLogger->ShouldLogFor(level)) {
243 return ossNull;
244 }
245 return pLogger->GetStream();
246 }
247private:
248 Logger *pLogger;
249 LogLevel level;
250 std::ostringstream ossNull;
251};
252
253}
254
255extern simplelogger::Logger *logger;
256#define LOG(level) simplelogger::LogTransaction(logger, level, __FILE__, __LINE__, __FUNCTION__).GetStream()
257 