diff --git a/.gitmodules b/.gitmodules index 790311c..e2d6e59 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "Base"] path = Base - url = git@github.com:atalantestudio/ModuleBase + url = https://github.com/atalantestudio/ModuleBase branch = main \ No newline at end of file diff --git a/Base b/Base index e9e0903..367e49e 160000 --- a/Base +++ b/Base @@ -1 +1 @@ -Subproject commit e9e0903ae85622c84b8d7ce912f783762f6c0f06 +Subproject commit 367e49e1c9c47505e82250ee72a61a1154e3a48e diff --git a/scroll/ConsoleLogger/ConsoleLogger.hpp b/scroll/ConsoleLogger/ConsoleLogger.hpp index 1c19ca5..58925e5 100644 --- a/scroll/ConsoleLogger/ConsoleLogger.hpp +++ b/scroll/ConsoleLogger/ConsoleLogger.hpp @@ -3,9 +3,9 @@ #pragma once -#include "ConsoleEscapeCode.hpp" -#include "Logger/Logger.hpp" -#include "LogLevel.hpp" +#include "scroll/ConsoleEscapeCode.hpp" +#include "scroll/Logger/Logger.hpp" +#include "scroll/LogLevel.hpp" namespace scroll { class ConsoleLogger : public Logger { @@ -24,9 +24,6 @@ namespace scroll { template ConsoleLogger& operator<<(Argument&& argument); - template<> - ConsoleLogger& operator<<(ConsoleEscapeCode&& argument); - ConsoleLogger& padLeft(uint64 padding); ConsoleLogger& padRight(uint64 padding); @@ -67,4 +64,4 @@ namespace scroll { }; } -#include "ConsoleLogger.ipp" \ No newline at end of file +#include "scroll/ConsoleLogger/ConsoleLogger.ipp" \ No newline at end of file diff --git a/scroll/ConsoleLogger/ConsoleLogger.ipp b/scroll/ConsoleLogger/ConsoleLogger.ipp index c0572d5..e77eef0 100644 --- a/scroll/ConsoleLogger/ConsoleLogger.ipp +++ b/scroll/ConsoleLogger/ConsoleLogger.ipp @@ -14,9 +14,10 @@ namespace scroll { } inline ConsoleLogger::ConsoleLogger(std::ostream& stream, LogLevel minimumLogLevel, view source) : - Logger(minimumLogLevel, source), - stream(&stream) - {} + Logger(minimumLogLevel, source) + { + setOutputStream(stream); + } inline ConsoleLogger::~ConsoleLogger() { if (writingEscapeCodes) { @@ -30,6 +31,13 @@ namespace scroll { inline void ConsoleLogger::setOutputStream(std::ostream& stream) { this->stream = &stream; + + #if ATL_OPERATING_SYSTEM == ATL_OPERATING_SYSTEM_WINDOWS + const HANDLE hConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + ATL_ASSERT(hConsoleHandle != NULL && hConsoleHandle != INVALID_HANDLE_VALUE); + ATL_ASSERT(SetConsoleMode(hConsoleHandle, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING) > 0); + #endif } template @@ -82,7 +90,7 @@ namespace scroll { std::ostream& stream = std::cerr; writeLogHeader(stream, source, "TRACE", ConsoleEscapeCode::BACKGROUND_COLOR_WHITE, ConsoleEscapeCode::FOREGROUND_COLOR_BLACK); - writeIndented(stream, format("[]\nat []:[]", format(std::forward(argument)), file, line), getLogIndentation() - 2); + writeIndented(stream, format("[] (at []:[])", format(std::forward(argument)), file, line), getLogIndentation() - 2); stream << '\n'; } @@ -96,7 +104,7 @@ namespace scroll { std::ostream& stream = std::cerr; writeLogHeader(stream, source, "TRACE", ConsoleEscapeCode::BACKGROUND_COLOR_WHITE, ConsoleEscapeCode::FOREGROUND_COLOR_BLACK); - writeIndented(stream, format("[]\nat []:[]", format(pattern, std::forward(arguments)...), file, line), getLogIndentation() - 2); + writeIndented(stream, format("[] (at []:[])", format(pattern, std::forward(arguments)...), file, line), getLogIndentation() - 2); stream << '\n'; } @@ -195,7 +203,7 @@ namespace scroll { writeLogHeader(stream, source, "ERROR", ConsoleEscapeCode::BACKGROUND_COLOR_LIGHT_RED, ConsoleEscapeCode::FOREGROUND_COLOR_WHITE); stream << "\033[" << ConsoleEscapeCode::FOREGROUND_COLOR_LIGHT_RED << 'm'; - writeIndented(stream, format("[]\nat [] ([]:[])", format(std::forward(argument)), function, file, line), getLogIndentation() - 2); + writeIndented(stream, format("[] (in [], at []:[])", format(std::forward(argument)), function, file, line), getLogIndentation() - 2); stream << "\033[" << ConsoleEscapeCode::RESET_FOREGROUND_COLOR << "m\n"; } @@ -209,7 +217,7 @@ namespace scroll { writeLogHeader(stream, source, "ERROR", ConsoleEscapeCode::BACKGROUND_COLOR_LIGHT_RED, ConsoleEscapeCode::FOREGROUND_COLOR_WHITE); stream << "\033[" << ConsoleEscapeCode::FOREGROUND_COLOR_LIGHT_RED << 'm'; - writeIndented(stream, format("[]\nat [] ([]:[])", format(pattern, std::forward(arguments)...), function, file, line), getLogIndentation() - 2); + writeIndented(stream, format("[] (in [], at []:[])", format(pattern, std::forward(arguments)...), function, file, line), getLogIndentation() - 2); stream << "\033[" << ConsoleEscapeCode::RESET_FOREGROUND_COLOR << "m\n"; } } \ No newline at end of file diff --git a/scroll/Conversions.hpp b/scroll/Conversions.hpp index 9c54151..cf8565c 100644 --- a/scroll/Conversions.hpp +++ b/scroll/Conversions.hpp @@ -3,11 +3,11 @@ #pragma once -#include "ConsoleEscapeCode.hpp" +#include "scroll/ConsoleEscapeCode.hpp" namespace scroll { std::ostream& operator<<(std::ostream& stream, view view); std::ostream& operator<<(std::ostream& stream, ConsoleEscapeCode code); } -#include "Conversions.ipp" \ No newline at end of file +#include "scroll/Conversions.ipp" \ No newline at end of file diff --git a/scroll/FileLogger/FileLogger.hpp b/scroll/FileLogger/FileLogger.hpp index 945b51d..2daef70 100644 --- a/scroll/FileLogger/FileLogger.hpp +++ b/scroll/FileLogger/FileLogger.hpp @@ -3,8 +3,8 @@ #pragma once -#include "Logger/Logger.hpp" -#include "LogLevel.hpp" +#include "scroll/Logger/Logger.hpp" +#include "scroll/LogLevel.hpp" namespace scroll { class FileLogger : public Logger { @@ -49,4 +49,4 @@ namespace scroll { }; } -#include "FileLogger.ipp" \ No newline at end of file +#include "scroll/FileLogger/FileLogger.ipp" \ No newline at end of file diff --git a/scroll/FileLogger/FileLogger.ipp b/scroll/FileLogger/FileLogger.ipp index acb72e6..1d5d309 100644 --- a/scroll/FileLogger/FileLogger.ipp +++ b/scroll/FileLogger/FileLogger.ipp @@ -6,7 +6,7 @@ namespace scroll { Logger(minLogLevel, source), stream(stream) { - ASSERT(stream.is_open()); + ATL_ASSERT(stream.is_open()); } template @@ -16,7 +16,7 @@ namespace scroll { } writeLogHeader("TRACE"); - writeIndented(stream, format("[]\nat []:[]", format(std::forward(argument)), file, line), getLogIndentation() - 4); + writeIndented(stream, format("[] (at []:[])", format(std::forward(argument)), file, line), getLogIndentation() - 4); stream << '\n'; } @@ -28,7 +28,7 @@ namespace scroll { } writeLogHeader("TRACE"); - writeIndented(stream, format("[]\nat []:[]", format(pattern, std::forward(arguments)...), file, line), getLogIndentation() - 4); + writeIndented(stream, format("[] (at []:[])", format(pattern, std::forward(arguments)...), file, line), getLogIndentation() - 4); stream << '\n'; } @@ -112,7 +112,7 @@ namespace scroll { } writeLogHeader("ERROR"); - writeIndented(stream, format("[]\nat [] ([]:[])", format(std::forward(argument)), function, file, line), getLogIndentation() - 4); + writeIndented(stream, format("[] (in [], at []:[])", format(std::forward(argument)), function, file, line), getLogIndentation() - 4); stream << '\n'; } @@ -124,7 +124,7 @@ namespace scroll { } writeLogHeader("ERROR"); - writeIndented(stream, format("[]\nat [] ([]:[])", format(pattern, std::forward(arguments)...), function, file, line), getLogIndentation() - 4); + writeIndented(stream, format("[] (in [], at []:[])", format(pattern, std::forward(arguments)...), function, file, line), getLogIndentation() - 4); stream << '\n'; } diff --git a/scroll/Logger/Logger.hpp b/scroll/Logger/Logger.hpp index 303d5aa..1855e86 100644 --- a/scroll/Logger/Logger.hpp +++ b/scroll/Logger/Logger.hpp @@ -3,10 +3,15 @@ #pragma once -#include "LogLevel.hpp" +#include "scroll/LogLevel.hpp" namespace scroll { - class Logger { + template + struct ArgumentInjectionPattern { + static sequence argumentInjectionPattern; + }; + + class Logger : public ArgumentInjectionPattern<> { public: // Returns the current argument injection pattern. static view getArgumentInjectionPattern(); @@ -27,9 +32,7 @@ namespace scroll { static void writeIndented(std::ostream& stream, view text, uint64 indentation); private: - static sequence argumentInjectionPattern; - - static constexpr uint64 TIMESTAMP_SIZE = 14; + static constexpr uint64 TIMESTAMP_SIZE = 15; static constexpr uint64 MAX_LOG_LEVEL_NAME_SIZE = 7; public: @@ -48,4 +51,4 @@ namespace scroll { }; } -#include "Logger.ipp" \ No newline at end of file +#include "scroll/Logger/Logger.ipp" \ No newline at end of file diff --git a/scroll/Logger/Logger.ipp b/scroll/Logger/Logger.ipp index 1456533..11be602 100644 --- a/scroll/Logger/Logger.ipp +++ b/scroll/Logger/Logger.ipp @@ -2,13 +2,20 @@ // Licensed under MIT. namespace scroll { + template + sequence ArgumentInjectionPattern::argumentInjectionPattern = "[]"; + template sequence Logger::format(Argument&& argument) { - std::ostringstream stream; + static std::ostringstream stream; stream << argument; - return stream.str().c_str(); + const sequence formattedArgument = stream.str().c_str(); + + stream.str({}); + + return formattedArgument; } template @@ -23,46 +30,61 @@ namespace scroll { sequence updatedPattern(pattern.count() - argumentInjectionPattern.count() + formattedArgument.count()); - std::copy_n(&pattern[0], argumentInjectionPatternOffset, &updatedPattern[0]); - std::copy(formattedArgument.begin(), formattedArgument.end(), &updatedPattern[argumentInjectionPatternOffset]); + copy(&pattern[0], &pattern[argumentInjectionPatternOffset], &updatedPattern[0]); + copy(formattedArgument.begin(), formattedArgument.end(), &updatedPattern[argumentInjectionPatternOffset]); if (argumentInjectionPatternOffset + argumentInjectionPattern.count() < pattern.count()) { - std::copy(&pattern[argumentInjectionPatternOffset + argumentInjectionPattern.count()], pattern.end(), &updatedPattern[argumentInjectionPatternOffset + formattedArgument.count()]); + copy(&pattern[argumentInjectionPatternOffset + argumentInjectionPattern.count()], pattern.end(), &updatedPattern[argumentInjectionPatternOffset + formattedArgument.count()]); } return format(updatedPattern, std::forward(arguments)...); } - inline sequence Logger::argumentInjectionPattern = "[]"; - inline view Logger::getArgumentInjectionPattern() { return argumentInjectionPattern; } inline void Logger::setArgumentInjectionPattern(view pattern) { - ASSERT(pattern.count() > 0); + ATL_ASSERT(pattern.count() > 0); argumentInjectionPattern = &pattern[0]; } inline sequence Logger::timestamp() { + static std::ostringstream usStream; + const std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - const uint64 ms = std::chrono::duration_cast(now - std::chrono::time_point_cast(now)).count(); + const uint64 us = std::chrono::duration_cast(now - std::chrono::time_point_cast(now)).count(); const std::time_t time = std::chrono::system_clock::to_time_t(now); - std::tm dateTime; + std::tm* dateTime; + + #ifdef _MSC_VER + std::tm _dateTime{}; - localtime_s(&dateTime, &time); + const errno_t error = localtime_s(&_dateTime, &time); - // NOTE: std::strftime writes the null-terminating character. + ATL_ASSERT(error == 0); + + dateTime = &_dateTime; + #else + dateTime = std::localtime(&time); + #endif + + // Include null-terminating character. sequence hmsString(9); - ASSERT(std::strftime(&hmsString[0], hmsString.count(), "%T", &dateTime) > 0); + const uint64 hmsCharacterCount = std::strftime(&hmsString[0], hmsString.count(), "%H:%M:%S", dateTime); + + ATL_ASSERT(hmsCharacterCount > 0); + + usStream << std::setw(6) << std::setfill('0') << us; + + const sequence timestamp = format("[].[]", hmsString, usStream.str()); - std::ostringstream msStream; - msStream << std::setw(3) << std::setfill('0') << ms; + usStream.str({}); - return format("[].[]", hmsString, msStream.str()); + return timestamp; } inline LogLevel Logger::getMinLogLevel() const { @@ -79,7 +101,7 @@ namespace scroll { {} inline uint16 Logger::getLogIndentation() const { - uint16 indentation = static_cast(TIMESTAMP_SIZE + MAX_LOG_LEVEL_NAME_SIZE + 4); + uint16 indentation = static_cast(TIMESTAMP_SIZE + MAX_LOG_LEVEL_NAME_SIZE + 6); if (source.count() > 0) { indentation += static_cast(source.count()) + 1; diff --git a/scroll/base.hpp b/scroll/base.hpp index ebf80e4..31607de 100644 --- a/scroll/base.hpp +++ b/scroll/base.hpp @@ -4,8 +4,10 @@ #pragma once #include +#include #include #include +#include #include #include @@ -13,6 +15,14 @@ #include "Base/Base/Base.hpp" #endif +#if ATL_OPERATING_SYSTEM == ATL_OPERATING_SYSTEM_WINDOWS + #include + + #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING + #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 + #endif +#endif + namespace scroll { using atl::uint8; using atl::uint16; @@ -23,4 +33,6 @@ namespace scroll { using atl::sequence; using atl::view; + + using atl::copy; } \ No newline at end of file diff --git a/scroll/scroll.hpp b/scroll/scroll.hpp index 0b0f32a..3e8933a 100644 --- a/scroll/scroll.hpp +++ b/scroll/scroll.hpp @@ -3,9 +3,7 @@ #pragma once -#include "base.hpp" - -#include "Conversions.hpp" - -#include "ConsoleLogger/ConsoleLogger.hpp" -#include "FileLogger/FileLogger.hpp" \ No newline at end of file +#include "scroll/base.hpp" +#include "scroll/Conversions.hpp" +#include "scroll/ConsoleLogger/ConsoleLogger.hpp" +#include "scroll/FileLogger/FileLogger.hpp" \ No newline at end of file