forked from sascha/godot
commit
132ba0ed97
@ -0,0 +1,252 @@
|
||||
/*************************************************************************/
|
||||
/* logger.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "logger.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/os.h"
|
||||
#include "print_string.h"
|
||||
|
||||
bool Logger::should_log(bool p_err) {
|
||||
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
|
||||
}
|
||||
|
||||
void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *err_type = "**ERROR**";
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: err_type = "**ERROR**"; break;
|
||||
case ERR_WARNING: err_type = "**WARNING**"; break;
|
||||
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
|
||||
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
|
||||
default: ERR_PRINT("Unknown error type"); break;
|
||||
}
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && *p_rationale)
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
logf_error("%s: %s\n", err_type, err_details);
|
||||
logf_error(" At: %s:%i:%s() - %s\n", p_file, p_line, p_function, p_code);
|
||||
}
|
||||
|
||||
void Logger::logf(const char *p_format, ...) {
|
||||
if (!should_log(false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
|
||||
logv(p_format, argp, false);
|
||||
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void Logger::logf_error(const char *p_format, ...) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
|
||||
logv(p_format, argp, true);
|
||||
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
Logger::~Logger() {}
|
||||
|
||||
void RotatedFileLogger::close_file() {
|
||||
if (file) {
|
||||
memdelete(file);
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RotatedFileLogger::clear_old_backups() {
|
||||
int max_backups = max_files - 1; // -1 for the current file
|
||||
|
||||
String basename = base_path.get_basename();
|
||||
String extension = "." + base_path.get_extension();
|
||||
|
||||
DirAccess *da = DirAccess::open(base_path.get_base_dir());
|
||||
if (!da) {
|
||||
return;
|
||||
}
|
||||
|
||||
da->list_dir_begin();
|
||||
String f = da->get_next();
|
||||
Set<String> backups;
|
||||
while (f != String()) {
|
||||
if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path) {
|
||||
backups.insert(f);
|
||||
}
|
||||
f = da->get_next();
|
||||
}
|
||||
da->list_dir_end();
|
||||
|
||||
if (backups.size() > max_backups) {
|
||||
// since backups are appended with timestamp and Set iterates them in sorted order,
|
||||
// first backups are the oldest
|
||||
int to_delete = backups.size() - max_backups;
|
||||
for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) {
|
||||
da->remove(E->get());
|
||||
}
|
||||
}
|
||||
|
||||
memdelete(da);
|
||||
}
|
||||
|
||||
void RotatedFileLogger::rotate_file() {
|
||||
close_file();
|
||||
|
||||
if (FileAccess::exists(base_path)) {
|
||||
if (max_files > 1) {
|
||||
char timestamp[21];
|
||||
OS::Date date = OS::get_singleton()->get_date();
|
||||
OS::Time time = OS::get_singleton()->get_time();
|
||||
sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day + 1, time.hour, time.min, time.sec);
|
||||
|
||||
String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
|
||||
|
||||
DirAccess *da = DirAccess::open(base_path.get_base_dir());
|
||||
if (da) {
|
||||
da->copy(base_path, backup_name);
|
||||
memdelete(da);
|
||||
}
|
||||
clear_old_backups();
|
||||
}
|
||||
} else {
|
||||
DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
|
||||
if (da) {
|
||||
da->make_dir_recursive(base_path.get_base_dir());
|
||||
memdelete(da);
|
||||
}
|
||||
}
|
||||
|
||||
file = FileAccess::open(base_path, FileAccess::WRITE);
|
||||
}
|
||||
|
||||
RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
|
||||
file = NULL;
|
||||
base_path = p_base_path.simplify_path();
|
||||
max_files = p_max_files > 0 ? p_max_files : 1;
|
||||
|
||||
rotate_file();
|
||||
}
|
||||
|
||||
void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
const int static_buf_size = 512;
|
||||
char static_buf[static_buf_size];
|
||||
char *buf = static_buf;
|
||||
int len = vsnprintf(buf, static_buf_size, p_format, p_list);
|
||||
if (len >= static_buf_size) {
|
||||
buf = (char *)Memory::alloc_static(len + 1);
|
||||
vsnprintf(buf, len + 1, p_format, p_list);
|
||||
}
|
||||
file->store_buffer((uint8_t *)buf, len);
|
||||
if (len >= static_buf_size) {
|
||||
Memory::free_static(buf);
|
||||
}
|
||||
#ifdef DEBUG_ENABLED
|
||||
const bool need_flush = true;
|
||||
#else
|
||||
bool need_flush = p_err;
|
||||
#endif
|
||||
if (need_flush) {
|
||||
file->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RotatedFileLogger::~RotatedFileLogger() {
|
||||
close_file();
|
||||
}
|
||||
|
||||
void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_err) {
|
||||
vfprintf(stderr, p_format, p_list);
|
||||
} else {
|
||||
vprintf(p_format, p_list);
|
||||
#ifdef DEBUG_ENABLED
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
StdLogger::~StdLogger() {}
|
||||
|
||||
CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
|
||||
loggers = p_loggers;
|
||||
}
|
||||
|
||||
void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loggers.size(); ++i) {
|
||||
va_list list_copy;
|
||||
va_copy(list_copy, p_list);
|
||||
loggers[i]->logv(p_format, list_copy, p_err);
|
||||
va_end(list_copy);
|
||||
}
|
||||
}
|
||||
|
||||
void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loggers.size(); ++i) {
|
||||
loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
}
|
||||
}
|
||||
|
||||
CompositeLogger::~CompositeLogger() {
|
||||
for (int i = 0; i < loggers.size(); ++i) {
|
||||
memdelete(loggers[i]);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
/*************************************************************************/
|
||||
/* logger.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include "os/file_access.h"
|
||||
#include "ustring.h"
|
||||
#include "vector.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
class Logger {
|
||||
protected:
|
||||
bool should_log(bool p_err);
|
||||
|
||||
public:
|
||||
enum ErrorType {
|
||||
ERR_ERROR,
|
||||
ERR_WARNING,
|
||||
ERR_SCRIPT,
|
||||
ERR_SHADER
|
||||
};
|
||||
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0;
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
void logf(const char *p_format, ...);
|
||||
void logf_error(const char *p_format, ...);
|
||||
|
||||
virtual ~Logger();
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes messages to stdout/stderr.
|
||||
*/
|
||||
class StdLogger : public Logger {
|
||||
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual ~StdLogger();
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes messages to the specified file. If the file already exists, creates a copy (backup)
|
||||
* of it with timestamp appended to the file name. Maximum number of backups is configurable.
|
||||
* When maximum is reached, the oldest backups are erased. With the maximum being equal to 1,
|
||||
* it acts as a simple file logger.
|
||||
*/
|
||||
class RotatedFileLogger : public Logger {
|
||||
String base_path;
|
||||
int max_files;
|
||||
|
||||
FileAccess *file;
|
||||
|
||||
void rotate_file_without_closing();
|
||||
void close_file();
|
||||
void clear_old_backups();
|
||||
void rotate_file();
|
||||
|
||||
public:
|
||||
RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
|
||||
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
|
||||
virtual ~RotatedFileLogger();
|
||||
};
|
||||
|
||||
class CompositeLogger : public Logger {
|
||||
Vector<Logger *> loggers;
|
||||
|
||||
public:
|
||||
CompositeLogger(Vector<Logger *> p_loggers);
|
||||
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
|
||||
virtual ~CompositeLogger();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,71 @@
|
||||
/*************************************************************************/
|
||||
/* syslog_logger.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "syslog_logger.h"
|
||||
#include "print_string.h"
|
||||
#include <syslog.h>
|
||||
|
||||
void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vsyslog(p_err ? LOG_ERR : LOG_INFO, p_format, p_list);
|
||||
}
|
||||
|
||||
void SyslogLogger::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *err_type = "**ERROR**";
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: err_type = "**ERROR**"; break;
|
||||
case ERR_WARNING: err_type = "**WARNING**"; break;
|
||||
case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
|
||||
case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
|
||||
default: ERR_PRINT("Unknown error type"); break;
|
||||
}
|
||||
|
||||
const char *err_details;
|
||||
if (p_rationale && *p_rationale)
|
||||
err_details = p_rationale;
|
||||
else
|
||||
err_details = p_code;
|
||||
|
||||
syslog(p_type == ERR_WARNING ? LOG_WARNING : LOG_ERR, "%s: %s\n At: %s:%i:%s() - %s", err_type, err_details, p_file, p_line, p_function, p_code);
|
||||
}
|
||||
|
||||
SyslogLogger::~SyslogLogger() {
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,48 @@
|
||||
/*************************************************************************/
|
||||
/* syslog_logger.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef SYSLOG_LOGGER_H
|
||||
#define SYSLOG_LOGGER_H
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "io/logger.h"
|
||||
|
||||
class SyslogLogger : public Logger {
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
|
||||
|
||||
virtual ~SyslogLogger();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,157 @@
|
||||
/*************************************************************************/
|
||||
/* windows_terminal_logger.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "windows_terminal_logger.h"
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_err) {
|
||||
if (!should_log(p_err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int BUFFER_SIZE = 16384;
|
||||
char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
|
||||
int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
|
||||
if (len <= 0)
|
||||
return;
|
||||
if (len >= BUFFER_SIZE)
|
||||
len = BUFFER_SIZE; // Output is too big, will be truncated
|
||||
buf[len] = 0;
|
||||
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
|
||||
if (wlen < 0)
|
||||
return;
|
||||
|
||||
wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
|
||||
wbuf[wlen] = 0;
|
||||
|
||||
if (p_err)
|
||||
fwprintf(stderr, L"%ls", wbuf);
|
||||
else
|
||||
wprintf(L"%ls", wbuf);
|
||||
|
||||
free(wbuf);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
|
||||
if (!should_log(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef UWP_ENABLED
|
||||
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (!hCon || hCon == INVALID_HANDLE_VALUE) {
|
||||
#endif
|
||||
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
|
||||
#ifndef UWP_ENABLED
|
||||
} else {
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
|
||||
GetConsoleScreenBufferInfo(hCon, &sbi);
|
||||
|
||||
WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
|
||||
|
||||
uint32_t basecol = 0;
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: basecol = FOREGROUND_RED; break;
|
||||
case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
|
||||
case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
|
||||
case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
|
||||
}
|
||||
|
||||
basecol |= current_bg;
|
||||
|
||||
if (p_rationale && p_rationale[0]) {
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf("ERROR: "); break;
|
||||
case ERR_WARNING: logf("WARNING: "); break;
|
||||
case ERR_SCRIPT: logf("SCRIPT ERROR: "); break;
|
||||
case ERR_SHADER: logf("SHADER ERROR: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
|
||||
logf("%s\n", p_rationale);
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf(" At: "); break;
|
||||
case ERR_WARNING: logf(" At: "); break;
|
||||
case ERR_SCRIPT: logf(" At: "); break;
|
||||
case ERR_SHADER: logf(" At: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg);
|
||||
logf("%s:%i\n", p_file, p_line);
|
||||
|
||||
} else {
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf("ERROR: %s: ", p_function); break;
|
||||
case ERR_WARNING: logf("WARNING: %s: ", p_function); break;
|
||||
case ERR_SCRIPT: logf("SCRIPT ERROR: %s: ", p_function); break;
|
||||
case ERR_SHADER: logf("SCRIPT ERROR: %s: ", p_function); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
|
||||
logf("%s\n", p_code);
|
||||
|
||||
SetConsoleTextAttribute(hCon, basecol);
|
||||
switch (p_type) {
|
||||
case ERR_ERROR: logf(" At: "); break;
|
||||
case ERR_WARNING: logf(" At: "); break;
|
||||
case ERR_SCRIPT: logf(" At: "); break;
|
||||
case ERR_SHADER: logf(" At: "); break;
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, current_fg | current_bg);
|
||||
logf("%s:%i\n", p_file, p_line);
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(hCon, sbi.wAttributes);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
WindowsTerminalLogger::~WindowsTerminalLogger() {}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,47 @@
|
||||
/*************************************************************************/
|
||||
/* windows_terminal_logger.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef WINDOWS_TERMINAL_LOGGER_H
|
||||
#define WINDOWS_TERMINAL_LOGGER_H
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
|
||||
#include "io/logger.h"
|
||||
|
||||
class WindowsTerminalLogger : public StdLogger {
|
||||
public:
|
||||
virtual void logv(const char *p_format, va_list p_list, bool p_err);
|
||||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
|
||||
virtual ~WindowsTerminalLogger();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue