From 7d5ce3db0d0fa406bc7624f8b7342db7ff8e3905 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 15 Mar 2021 17:25:14 +0100 Subject: [PATCH] WIP: Add lcf logger --- CMakeLists.txt | 3 ++ Makefile.am | 3 ++ src/lcf/log_handler.h | 47 +++++++++++++++++++++++ src/log.h | 24 ++++++++++++ src/log_handler.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++ src/lsd_reader.cpp | 3 +- src/reader_lcf.cpp | 3 +- 7 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/lcf/log_handler.h create mode 100644 src/log.h create mode 100644 src/log_handler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 14ab6bf7..f48e8e26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,9 @@ set(LCF_SOURCES src/lmt_treemap.cpp src/lmu_movecommand.cpp src/lmu_reader.cpp + src/log.h src/lsd_reader.cpp + src/log_handler.cpp src/reader_flags.cpp src/reader_lcf.cpp src/reader_struct.h @@ -208,6 +210,7 @@ set(LCF_HEADERS src/lcf/lmt/reader.h src/lcf/lmu/reader.h src/lcf/lsd/reader.h + src/lcf/log_handler.h src/lcf/reader_lcf.h src/lcf/reader_util.h src/lcf/reader_xml.h diff --git a/Makefile.am b/Makefile.am index d378e2be..fe10c1e7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,7 +57,9 @@ liblcf_la_SOURCES = \ src/lmt_treemap.cpp \ src/lmu_movecommand.cpp \ src/lmu_reader.cpp \ + src/log.h \ src/lsd_reader.cpp \ + src/log_handler.cpp \ src/reader_flags.cpp \ src/reader_lcf.cpp \ src/reader_struct.h \ @@ -219,6 +221,7 @@ lcfinclude_HEADERS = \ src/lcf/flag_set.h \ src/lcf/ini.h \ src/lcf/inireader.h \ + src/lcf/log_handler.h \ src/lcf/reader_lcf.h \ src/lcf/reader_util.h \ src/lcf/reader_xml.h \ diff --git a/src/lcf/log_handler.h b/src/lcf/log_handler.h new file mode 100644 index 00000000..c6eb69ac --- /dev/null +++ b/src/lcf/log_handler.h @@ -0,0 +1,47 @@ +/* + * This file is part of liblcf. Copyright (c) 2020 liblcf authors. + * https://github.com/EasyRPG/liblcf - https://easyrpg.org + * + * liblcf is Free/Libre Open Source Software, released under the MIT License. + * For the full copyright and license information, please view the COPYING + * file that was distributed with this source code. + */ + +#ifndef LCF_OUTPUT_H +#define LCF_OUTPUT_H + +#include "string_view.h" + +namespace lcf { +namespace LogHandler { + +enum class Level { + Debug, + Warning, + Error, + Highest +}; + +using LogHandlerFn = void (*)(Level level, StringView message); + +/** + * Sets the output handler for all lcf logging. + * The default handler prints to standard error. + * + * @param fn New output handler. nullptr for default handler. + */ +void SetHandler(LogHandlerFn fn); + +/** + * Only report issues that have at least this log level. + * Use Highest to disable logging. + * Default: Debug + * + * @param new_level New log level + */ +void SetLevel(Level new_level); + +} // namespace LogHandler +} // namespace lcf + +#endif diff --git a/src/log.h b/src/log.h new file mode 100644 index 00000000..d2915102 --- /dev/null +++ b/src/log.h @@ -0,0 +1,24 @@ +/* + * This file is part of liblcf. Copyright (c) 2020 liblcf authors. + * https://github.com/EasyRPG/liblcf - https://easyrpg.org + * + * liblcf is Free/Libre Open Source Software, released under the MIT License. + * For the full copyright and license information, please view the COPYING + * file that was distributed with this source code. + */ + +#ifndef LCF_LOG_H +#define LCF_LOG_H + +#include "lcf/log_handler.h" + +namespace lcf { +namespace Log { + +void Debug(const char* fmt, ...); +void Warning(const char* fmt, ...); + +} // namespace Log +} // namespace lcf + +#endif diff --git a/src/log_handler.cpp b/src/log_handler.cpp new file mode 100644 index 00000000..36855cee --- /dev/null +++ b/src/log_handler.cpp @@ -0,0 +1,88 @@ +/* + * This file is part of liblcf. Copyright (c) 2020 liblcf authors. + * https://github.com/EasyRPG/liblcf - https://easyrpg.org + * + * liblcf is Free/Libre Open Source Software, released under the MIT License. + * For the full copyright and license information, please view the COPYING + * file that was distributed with this source code. + */ + +#include "lcf/log_handler.h" +#include +#include +#include +#include + +namespace lcf { +namespace LogHandler { +namespace { + void DefaultHandler(lcf::LogHandler::Level level, StringView message) { + switch (level) { + case Level::Debug: + std::cerr << "Debug: "; + break; + case Level::Warning: + std::cerr << "Warning: "; + break; + case Level::Error: + std::cerr << "Error: "; + break; + default: + assert(false && "Invalid Log Level"); + } + std::cerr << message << "\n"; + } + + Level level = Level::Debug; + LogHandlerFn output_fn = DefaultHandler; +} + +void SetHandler(LogHandlerFn fn) { + if (!fn) { + output_fn = DefaultHandler; + } else { + output_fn = fn; + } +} + +void SetLevel(Level new_level) { + level = new_level; +} + +} // namespace Output + +namespace Log { +namespace { + std::string format_string(char const* fmt, va_list args) { + char buf[4096]; + int const result = vsnprintf(buf, sizeof(buf), fmt, args); + if (result < 0) { + return std::string(); + } + + return std::string(buf, static_cast(result) < sizeof(buf) ? result : sizeof(buf)); + } +} + +void Debug(const char* fmt, ...) { + if (static_cast(LogHandler::Level::Debug) >= static_cast(LogHandler::level)) { + va_list args; + va_start(args, fmt); + auto msg = format_string(fmt, args); + LogHandler::output_fn(LogHandler::Level::Debug, msg); + va_end(args); + } +} + +void Warning(const char* fmt, ...) { + if (static_cast(LogHandler::Level::Warning) >= static_cast(LogHandler::level)) { + va_list args; + va_start(args, fmt); + auto msg = format_string(fmt, args); + LogHandler::output_fn(LogHandler::Level::Warning, msg); + va_end(args); + } +} + +} // namespace Log +} // namespace lcf diff --git a/src/lsd_reader.cpp b/src/lsd_reader.cpp index cc64a44e..60af4cad 100644 --- a/src/lsd_reader.cpp +++ b/src/lsd_reader.cpp @@ -16,6 +16,7 @@ #include "lcf/lsd/chunks.h" #include "lcf/rpg/save.h" #include "lcf/reader_util.h" +#include "log.h" #include "reader_struct.h" namespace lcf { @@ -43,7 +44,7 @@ void LSD_Reader::PrepareSave(rpg::Save& save, int32_t version, int32_t codepage) std::unique_ptr LSD_Reader::Load(StringView filename, StringView encoding) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { - fprintf(stderr, "Failed to open LSD file `%s' for reading : %s\n", ToString(filename).c_str(), strerror(errno)); + lcf::Log::Warning("Failed to open LSD file '%s' for reading : %s", ToString(filename).c_str(), strerror(errno)); return nullptr; } return LSD_Reader::Load(stream, encoding); diff --git a/src/reader_lcf.cpp b/src/reader_lcf.cpp index 4c6ff0b3..6ab9ea52 100644 --- a/src/reader_lcf.cpp +++ b/src/reader_lcf.cpp @@ -13,6 +13,7 @@ #include #include "lcf/reader_lcf.h" +#include "log.h" namespace lcf { // Statics @@ -276,7 +277,7 @@ int LcfReader::Peek() { } void LcfReader::Skip(const struct LcfReader::Chunk& chunk_info, const char* where) { - fprintf(stderr, "Skipped Chunk %02X (%" PRIu32 " byte) in lcf at %" PRIX32 " (%s)\n", + Log::Debug("Skipped Chunk %02X (%" PRIu32 " byte) in lcf at %" PRIX32 " (%s)\n", chunk_info.ID, chunk_info.length, Tell(), where); for (uint32_t i = 0; i < chunk_info.length; ++i) {