/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 * * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ #include "Diagnostic.h" #include "core/Console.hpp" #include "core/String.hpp" #include #include #ifdef __ANDROID__ # include #endif [[maybe_unused]] static bool _log_location_enabled = true; bool _log_levels[static_cast(DiagnosticLevel::Count)] = { true, true, true, false, true }; static FILE* diagnostic_get_stream(DiagnosticLevel level) { switch (level) { case DiagnosticLevel::Verbose: case DiagnosticLevel::Information: return stdout; default: return stderr; } } #ifdef __ANDROID__ int _android_log_priority[static_cast(DiagnosticLevel::Count)] = { ANDROID_LOG_FATAL, ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_VERBOSE, ANDROID_LOG_INFO }; void diagnostic_log(DiagnosticLevel diagnosticLevel, const char* format, ...) { va_list args; if (!_log_levels[static_cast(diagnosticLevel)]) return; va_start(args, format); __android_log_vprint(_android_log_priority[static_cast(diagnosticLevel)], "OpenRCT2", format, args); va_end(args); } void diagnostic_log_with_location( DiagnosticLevel diagnosticLevel, const char* file, const char* function, int32_t line, const char* format, ...) { va_list args; char buf[1024]; if (!_log_levels[static_cast(diagnosticLevel)]) return; snprintf(buf, 1024, "[%s:%d (%s)]: ", file, line, function); va_start(args, format); __android_log_vprint(_android_log_priority[static_cast(diagnosticLevel)], file, format, args); va_end(args); } #else static constexpr const char* _level_strings[] = { "FATAL", "ERROR", "WARNING", "VERBOSE", "INFO", }; static void diagnostic_print(DiagnosticLevel level, const std::string& prefix, const std::string& msg) { auto stream = diagnostic_get_stream(level); if (stream == stdout) Console::WriteLine("%s%s", prefix.c_str(), msg.c_str()); else Console::Error::WriteLine("%s%s", prefix.c_str(), msg.c_str()); } void diagnostic_log(DiagnosticLevel diagnosticLevel, const char* format, ...) { va_list args; if (_log_levels[static_cast(diagnosticLevel)]) { // Level auto prefix = String::StdFormat("%s: ", _level_strings[static_cast(diagnosticLevel)]); // Message va_start(args, format); auto msg = String::StdFormat_VA(format, args); va_end(args); diagnostic_print(diagnosticLevel, prefix, msg); } } void diagnostic_log_with_location( DiagnosticLevel diagnosticLevel, const char* file, const char* function, int32_t line, const char* format, ...) { va_list args; if (_log_levels[static_cast(diagnosticLevel)]) { // Level and source code information std::string prefix; if (_log_location_enabled) { prefix = String::StdFormat( "%s[%s:%d (%s)]: ", _level_strings[static_cast(diagnosticLevel)], file, line, function); } else { prefix = String::StdFormat("%s: ", _level_strings[static_cast(diagnosticLevel)]); } // Message va_start(args, format); auto msg = String::StdFormat_VA(format, args); va_end(args); diagnostic_print(diagnosticLevel, prefix, msg); } } #endif // __ANDROID__