From d646fbb94fcc81a1e642b9e6792ef3bac1ec8bf3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 5 Aug 2016 19:49:45 +0300 Subject: [PATCH] Fmt/Log fixes --- Utilities/Log.cpp | 27 ++-- Utilities/Log.h | 17 +- Utilities/StrFmt.cpp | 56 +++++-- Utilities/StrFmt.h | 73 ++++----- Utilities/cfmt.h | 329 +++++++++++++++++++++++++++++--------- rpcs3/Gui/ConLogFrame.cpp | 10 +- 6 files changed, 355 insertions(+), 157 deletions(-) diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 62a5b5a293..80234afafe 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -56,7 +56,7 @@ namespace logs } // Encode level, current thread name, channel name and write log message - virtual void log(const message& msg) override; + virtual void log(const message& msg, const std::string& prefix, const std::string& text) override; }; static file_listener* get_logger() @@ -88,27 +88,18 @@ void logs::listener::add(logs::listener* _new) } } -void logs::channel::broadcast(const logs::channel& ch, logs::level sev, const char* fmt, const fmt::supplementary_info* sup, const u64* args) +void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u64* args) { std::string text; fmt::raw_append(text, fmt, sup, args); std::string prefix(g_tls_log_prefix ? g_tls_log_prefix() : ""); - // Prepare message information - message msg; - msg.ch = &ch; - msg.sev = sev; - msg.text = text.data(); - msg.text_size = text.size(); - msg.prefix = prefix.data(); - msg.prefix_size = prefix.size(); - // Get first (main) listener listener* lis = get_logger(); // Send message to all listeners while (lis) { - lis->log(msg); + lis->log(*this, prefix, text); lis = lis->m_next; } } @@ -135,9 +126,9 @@ void logs::file_writer::log(const char* text, std::size_t size) m_file.write(text, size); } -void logs::file_listener::log(const logs::message& msg) +void logs::file_listener::log(const logs::message& msg, const std::string& prefix, const std::string& _text) { - std::string text; text.reserve(msg.text_size + msg.prefix_size + 200); + std::string text; text.reserve(prefix.size() + _text.size() + 200); // Used character: U+00B7 (Middle Dot) switch (msg.sev) @@ -154,9 +145,11 @@ void logs::file_listener::log(const logs::message& msg) // TODO: print time? - if (msg.prefix_size > 0) + if (prefix.size() > 0) { - text += fmt::format("{%s} ", msg.prefix); + text += "{"; + text += prefix; + text += "} "; } if (msg.ch->name) @@ -169,7 +162,7 @@ void logs::file_listener::log(const logs::message& msg) text += "TODO: "; } - text += msg.text; + text += _text; text += '\n'; file_writer::log(text.data(), text.size()); diff --git a/Utilities/Log.h b/Utilities/Log.h index b3ad9501e4..fec55e3fba 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -27,10 +27,8 @@ namespace logs const channel* ch; level sev; - const char* prefix; - std::size_t prefix_size; - const char* text; - std::size_t text_size; + // Send log message to global logger instance + void broadcast(const char*, const fmt_type_info*, const u64*); }; class listener @@ -38,7 +36,7 @@ namespace logs // Next listener (linked list) atomic_t m_next{}; - friend struct channel; + friend struct message; public: constexpr listener() = default; @@ -46,7 +44,7 @@ namespace logs virtual ~listener() = default; // Process log message - virtual void log(const message& msg) = 0; + virtual void log(const message& msg, const std::string& prefix, const std::string& text) = 0; // Add new listener static void add(listener*); @@ -69,11 +67,11 @@ namespace logs // Formatting function template - SAFE_BUFFERS void format(level sev, const char* fmt, const Args&... args) const + SAFE_BUFFERS FORCE_INLINE void format(level sev, const char* fmt, const Args&... args) const { if (UNLIKELY(sev <= enabled)) { - broadcast(*this, sev, fmt, fmt::arg_type_info::get::type...>(), fmt::args_t{::fmt_unveil::get(args)...}); + message{this, sev}.broadcast(fmt, fmt_type_info::get...>(), fmt_args_t{fmt_unveil::get(args)...}); } } @@ -93,9 +91,6 @@ namespace logs GEN_LOG_METHOD(trace) #undef GEN_LOG_METHOD - private: - // Send log message to global logger instance - static void broadcast(const channel& ch, level sev, const char*, const fmt::supplementary_info*, const u64*); }; /* Small set of predefined channels */ diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 4d01f2eabf..7618bb3aab 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -1,6 +1,7 @@ #include "StrFmt.h" #include "BEType.h" #include "StrUtil.h" +#include "Macro.h" #include "cfmt.h" #include @@ -10,6 +11,12 @@ void fmt_class_string::format(std::string& out, u64 arg) fmt::append(out, "%p", reinterpret_cast(static_cast(arg))); } +template<> +void fmt_class_string::format(std::string& out, u64 arg) +{ + fmt::append(out, "%p", reinterpret_cast(static_cast(arg))); +} + void fmt_class_string::format(std::string& out, u64 arg) { out += reinterpret_cast(static_cast(arg)); @@ -97,13 +104,13 @@ void fmt_class_string::format(std::string& out, u64 arg) template<> void fmt_class_string::format(std::string& out, u64 arg) { - fmt::append(out, "%f", static_cast(reinterpret_cast(arg))); + fmt::append(out, "%gf", static_cast(reinterpret_cast(arg))); } template<> void fmt_class_string::format(std::string& out, u64 arg) { - fmt::append(out, "%f", reinterpret_cast(arg)); + fmt::append(out, "%g", reinterpret_cast(arg)); } template<> @@ -127,24 +134,21 @@ namespace fmt // Temporary implementation struct fmt::cfmt_src { - const fmt::supplementary_info* sup; + const fmt_type_info* sup; const u64* args; - bool test(std::size_t index = 0) + bool test(std::size_t index) const { - for (std::size_t i = 0; i <= index; i++) + if (!sup[index].fmt_string) { - if (!sup[i].fmt_string) - { - return false; - } + return false; } return true; } template - T get(std::size_t index = 0) + T get(std::size_t index) const { return reinterpret_cast(args[index]); } @@ -155,20 +159,44 @@ struct fmt::cfmt_src ++args += extra; } - std::size_t fmt_string(std::string& out) + std::size_t fmt_string(std::string& out, std::size_t extra) const { const std::size_t start = out.size(); - sup->fmt_string(out, args[0]); + sup[extra].fmt_string(out, args[extra]); return out.size() - start; } + + // Returns type size (0 if unknown, pointer, assumed max) + std::size_t type(std::size_t extra) const + { + // Hack: use known function pointers to determine type +#define TYPE(type)\ + if (sup[extra].fmt_string == &fmt_class_string::format) return sizeof(type); + + TYPE(char); + TYPE(schar); + TYPE(uchar); + TYPE(short); + TYPE(ushort); + TYPE(int); + TYPE(uint); + TYPE(long); + TYPE(ulong); + TYPE(llong); + TYPE(ullong); + +#undef TYPE + + return 0; + } }; -void fmt::raw_append(std::string& out, const char* fmt, const fmt::supplementary_info* sup, const u64* args) noexcept +void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept { cfmt_append(out, fmt, cfmt_src{sup, args}); } -char* fmt::alloc_format(const char* fmt, const fmt::supplementary_info* sup, const u64* args) noexcept +char* fmt::alloc_format(const char* fmt, const fmt_type_info* sup, const u64* args) noexcept { std::string str; raw_append(str, fmt, sup, args); diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 85e9ec37ce..710b9494f6 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -155,48 +155,49 @@ struct fmt_class_string : fmt_class_string // Classify char* as const char* }; +struct fmt_type_info +{ + decltype(&fmt_class_string::format) fmt_string; + + template + static constexpr fmt_type_info make() + { + return fmt_type_info + { + &fmt_class_string::format, + }; + } + + template + static inline const fmt_type_info* get() + { + // Constantly initialized null-terminated list of type-specific information + static constexpr fmt_type_info result[sizeof...(Args) + 1] + { + make()... + }; + + return result; + } +}; + +template +using fmt_unveil_t = typename fmt_unveil::type; + +// Argument array type (each element generated via fmt_unveil<>) +template +using fmt_args_t = const u64(&&)[sizeof...(Args) + 1]; + namespace fmt { - // Argument array type (each element generated via fmt_unveil<>) - template - using args_t = const u64(&&)[sizeof...(Args) + 1]; - - using supplementary_info = const struct arg_type_info; - - struct arg_type_info - { - decltype(&fmt_class_string::format) fmt_string; - - template - static constexpr arg_type_info make() - { - return arg_type_info - { - &fmt_class_string::format, - }; - } - - template - static inline const supplementary_info* get() - { - // Constantly initialized null-terminated list of type-specific information - static constexpr arg_type_info result[sizeof...(Args) + 1] - { - make()... - }; - - return result; - } - }; - // Internal formatting function - void raw_append(std::string& out, const char*, const supplementary_info*, const u64*) noexcept; + void raw_append(std::string& out, const char*, const fmt_type_info*, const u64*) noexcept; // Formatting function template static SAFE_BUFFERS void append(std::string& out, const char* fmt, const Args&... args) { - raw_append(out, fmt, arg_type_info::get::type...>(), args_t{::fmt_unveil::get(args)...}); + raw_append(out, fmt, fmt_type_info::get...>(), fmt_args_t{fmt_unveil::get(args)...}); } // Formatting function @@ -209,7 +210,7 @@ namespace fmt } // Internal helper function - char* alloc_format(const char*, const supplementary_info*, const u64*) noexcept; + char* alloc_format(const char*, const fmt_type_info*, const u64*) noexcept; // Exception type with formatting constructor template @@ -220,7 +221,7 @@ namespace fmt public: template SAFE_BUFFERS exception_t(const char* fmt, const Args&... args) - : base((fmt = alloc_format(fmt, arg_type_info::get::type...>(), args_t{::fmt_unveil::get(args)...}))) + : base((fmt = alloc_format(fmt, fmt_type_info::get...>(), fmt_args_t{fmt_unveil::get(args)...}))) { std::free(const_cast(fmt)); } diff --git a/Utilities/cfmt.h b/Utilities/cfmt.h index 492c70190e..4480eb4460 100644 --- a/Utilities/cfmt.h +++ b/Utilities/cfmt.h @@ -3,17 +3,18 @@ #include "types.h" #include #include +#include /* C-style format parser. Appends formatted string to `out`, returns number of characters written. -Arguments are provided via `src`. TODO +`out`: mutable reference to std::string, std::vector or other compatible container +`fmt`: null-terminated string of `Char` type (char or constructible from char) +`src`: rvalue reference to argument provider. */ -template -Size cfmt_append(std::string& out, const char* fmt, Src&& src) +template +std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src) { - const std::size_t old_size = out.size(); - - out.reserve(old_size + 992); + const std::size_t start_pos = out.size(); struct cfmt_context { @@ -37,14 +38,13 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) // Error handling: print untouched sequence, stop further formatting const auto drop_sequence = [&] { - out.append(fmt - ctx.size, ctx.size); + out.insert(out.end(), fmt - ctx.size, fmt); ctx.size = -1; }; - // TODO: check overflow const auto read_decimal = [&](uint result) -> uint { - while (fmt[0] >= '0' && fmt[0] <= '9') + while (fmt[0] >= '0' && fmt[0] <= '9' && result <= (UINT_MAX / 10)) { result = result * 10 + (fmt[0] - '0'); fmt++, ctx.size++; @@ -53,24 +53,48 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) return result; }; - // TODO: remove this - const auto fallback = [&]() + const auto write_octal = [&](u64 value, u64 min_num) { - const std::string _fmt(fmt - ctx.size, fmt); + out.resize(out.size() + std::max(min_num, 66 / 3 - (cntlz64(value | 1) + 2) / 3), '0'); - const u64 arg0 = src.template get(); - const int arg1 = ctx.args >= 1 ? src.template get(1) : 0; - const int arg2 = ctx.args >= 2 ? src.template get(2) : 0; - - if (const std::size_t _size = std::snprintf(0, 0, _fmt.c_str(), arg0, arg1, arg2)) + // Write in reversed order + for (auto i = out.rbegin(); value; i++, value /= 8) { - out.resize(out.size() + _size); - std::snprintf(&out.front() + out.size() - _size, _size + 1, _fmt.c_str(), arg0, arg1, arg2); + *i = value % 8 + '0'; + } + }; + + const auto write_hex = [&](u64 value, bool upper, u64 min_num) + { + out.resize(out.size() + std::max(min_num, 64 / 4 - cntlz64(value | 1) / 4), '0'); + + // Write in reversed order + for (auto i = out.rbegin(); value; i++, value /= 16) + { + *i = (upper ? "0123456789ABCDEF" : "0123456789abcdef")[value % 16]; + } + }; + + const auto write_decimal = [&](u64 value, s64 min_size) + { + const std::size_t start = out.size(); + + do + { + out.push_back(value % 10 + '0'); + value /= 10; + } + while (0 < --min_size || value); + + // Revert written characters + for (std::size_t i = start, j = out.size() - 1; i < j; i++, j--) + { + std::swap(out[i], out[j]); } }; // Single pass over fmt string (null-terminated), TODO: check correct order - while (const char ch = *fmt++) if (ctx.size == 0) + while (const Char ch = *fmt++) if (ctx.size == 0) { if (ch == '%') { @@ -78,17 +102,17 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) } else { - out += ch; + out.push_back(ch); } } else if (ctx.size == 1 && ch == '%') { ctx = {0}; - out += ch; + out.push_back(ch); } else if (ctx.size == -1) { - out += ch; + out.push_back(ch); } else switch (ctx.size++, ch) { @@ -108,43 +132,58 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case '8': case '9': { - ctx.width = read_decimal(ch - '0'); + if (UNLIKELY(ctx.width)) + { + drop_sequence(); + } + else + { + ctx.width = read_decimal(ch - '0'); + } + break; } case '*': { - if (!src.test(++ctx.args)) + if (UNLIKELY(ctx.width || !src.test(ctx.args))) { drop_sequence(); - break; } - - const int warg = src.template get(ctx.args); - ctx.width = std::abs(warg); - ctx.left |= warg < 0; + else + { + const int warg = src.template get(ctx.args++); + ctx.width = std::abs(warg); + ctx.left |= warg < 0; + } + break; } case '.': { - if (*fmt >= '0' && *fmt <= '9') // TODO: does it allow '0'? + if (UNLIKELY(ctx.dot || ctx.prec)) + { + drop_sequence(); + } + else if (*fmt >= '0' && *fmt <= '9') // TODO: does it allow '0'? { ctx.prec = read_decimal(0); ctx.dot = true; } else if (*fmt == '*') { - if (!src.test(++ctx.args)) + if (UNLIKELY(!src.test(ctx.args))) { drop_sequence(); - break; } - - fmt++, ctx.size++; - const int parg = src.template get(ctx.args); - ctx.prec = parg; - ctx.dot = parg >= 0; + else + { + fmt++, ctx.size++; + const int parg = src.template get(ctx.args++); + ctx.prec = std::max(parg, 0); + ctx.dot = parg >= 0; + } } else { @@ -157,7 +196,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'h': { - if (ctx.type) + if (UNLIKELY(ctx.type)) { drop_sequence(); } @@ -176,7 +215,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'l': { - if (ctx.type) + if (UNLIKELY(ctx.type)) { drop_sequence(); } @@ -195,7 +234,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'z': { - if (ctx.type) + if (UNLIKELY(ctx.type)) { drop_sequence(); } @@ -209,7 +248,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'j': { - if (ctx.type) + if (UNLIKELY(ctx.type)) { drop_sequence(); } @@ -223,7 +262,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 't': { - if (ctx.type) + if (UNLIKELY(ctx.type)) { drop_sequence(); } @@ -237,19 +276,19 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'c': { - if (ctx.type || !src.test()) + if (UNLIKELY(ctx.type || !src.test(ctx.args))) { drop_sequence(); break; } const std::size_t start = out.size(); - out += src.template get(0); + out.push_back(src.template get(ctx.args)); if (1 < ctx.width) { // Add spaces if necessary - out.insert(start + ctx.left, ctx.width - 1, ' '); + out.insert(out.begin() + start + ctx.left, ctx.width - 1, ' '); } src.skip(ctx.args); @@ -259,14 +298,14 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 's': { - if (ctx.type || !src.test()) + if (UNLIKELY(ctx.type || !src.test(ctx.args))) { drop_sequence(); break; } const std::size_t start = out.size(); - const std::size_t size1 = src.fmt_string(out); + const std::size_t size1 = src.fmt_string(out, ctx.args); if (ctx.dot && size1 > ctx.prec) { @@ -274,13 +313,12 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) out.resize(start + ctx.prec); } - // TODO: how it works if precision and width specified simultaneously? const std::size_t size2 = out.size() - start; if (size2 < ctx.width) { // Add spaces if necessary - out.insert(ctx.left ? out.size() : start, ctx.width - size2, ' '); + out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' '); } src.skip(ctx.args); @@ -291,7 +329,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'd': case 'i': { - if (!src.test()) + if (UNLIKELY(!src.test(ctx.args))) { drop_sequence(); break; @@ -299,10 +337,48 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) if (!ctx.type) { - ctx.type = sizeof(int); + ctx.type = (u8)src.type(ctx.args); + } + + // Sign-extended argument expected: no special conversion + const u64 val = src.template get(ctx.args); + const s64 sval = val; + + const std::size_t start = out.size(); + + if (!ctx.dot || ctx.prec) + { + if (sval < 0) + { + out.push_back('-'); + } + else if (ctx.sign) + { + out.push_back('+'); + } + else if (ctx.space) + { + out.push_back(' '); + } + + write_decimal(sval < 0 ? 0 - val : val, ctx.prec); + } + + const std::size_t size2 = out.size() - start; + + if (size2 < ctx.width) + { + // Add padding if necessary + if (ctx.zeros && !ctx.left && !ctx.dot) + { + out.insert(out.begin() + start + (sval < 0 || ctx.sign || ctx.space), ctx.width - size2, '0'); + } + else + { + out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' '); + } } - fallback(); // TODO src.skip(ctx.args); ctx = {0}; break; @@ -310,7 +386,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'o': { - if (!src.test()) + if (UNLIKELY(!src.test(ctx.args))) { drop_sequence(); break; @@ -318,10 +394,40 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) if (!ctx.type) { - ctx.type = sizeof(int); + ctx.type = (u8)src.type(ctx.args); + } + + const u64 mask = + ctx.type == 1 ? 0xffull : + ctx.type == 2 ? 0xffffull : + ctx.type == 4 ? 0xffffffffull : 0xffffffffffffffffull; + + const u64 val = src.template get(ctx.args) & mask; + + const std::size_t start = out.size(); + + if (ctx.alter) + { + out.push_back('0'); + + if (val) + { + write_octal(val, ctx.prec ? ctx.prec - 1 : 0); + } + } + else if (!ctx.dot || ctx.prec) + { + write_octal(val, ctx.prec); + } + + const std::size_t size2 = out.size() - start; + + if (size2 < ctx.width) + { + // Add padding if necessary + out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ctx.zeros && !ctx.left && !ctx.dot ? '0' : ' '); } - fallback(); // TODO src.skip(ctx.args); ctx = {0}; break; @@ -330,7 +436,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'x': case 'X': { - if (!src.test()) + if (UNLIKELY(!src.test(ctx.args))) { drop_sequence(); break; @@ -338,10 +444,48 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) if (!ctx.type) { - ctx.type = sizeof(int); + ctx.type = (u8)src.type(ctx.args); + } + + const u64 mask = + ctx.type == 1 ? 0xffull : + ctx.type == 2 ? 0xffffull : + ctx.type == 4 ? 0xffffffffull : 0xffffffffffffffffull; + + const u64 val = src.template get(ctx.args) & mask; + + const std::size_t start = out.size(); + + if (ctx.alter) + { + out.push_back('0'); + + if (val) + { + out.push_back(ch); // Prepend 0x or 0X + write_hex(val, ch == 'X', ctx.prec); + } + } + else if (!ctx.dot || ctx.prec) + { + write_hex(val, ch == 'X', ctx.prec); + } + + const std::size_t size2 = out.size() - start; + + if (size2 < ctx.width) + { + // Add padding if necessary + if (ctx.zeros && !ctx.left && !ctx.dot) + { + out.insert(out.begin() + start + (ctx.alter && val ? 2 : 0), ctx.width - size2, '0'); + } + else + { + out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' '); + } } - fallback(); // TODO src.skip(ctx.args); ctx = {0}; break; @@ -349,7 +493,7 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'u': { - if (!src.test()) + if (UNLIKELY(!src.test(ctx.args))) { drop_sequence(); break; @@ -357,10 +501,31 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) if (!ctx.type) { - ctx.type = sizeof(int); + ctx.type = (u8)src.type(ctx.args); + } + + const u64 mask = + ctx.type == 1 ? 0xffull : + ctx.type == 2 ? 0xffffull : + ctx.type == 4 ? 0xffffffffull : 0xffffffffffffffffull; + + const u64 val = src.template get(ctx.args) & mask; + + const std::size_t start = out.size(); + + if (!ctx.dot || ctx.prec) + { + write_decimal(val, ctx.prec); + } + + const std::size_t size2 = out.size() - start; + + if (size2 < ctx.width) + { + // Add padding if necessary + out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ctx.zeros && !ctx.left && !ctx.dot ? '0' : ' '); } - fallback(); // TODO src.skip(ctx.args); ctx = {0}; break; @@ -368,19 +533,26 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'p': { - if (!src.test()) + if (UNLIKELY(!src.test(ctx.args) || ctx.type)) { drop_sequence(); break; } - if (ctx.type) - { - drop_sequence(); - break; - } + const u64 val = src.template get(ctx.args); - fallback(); // TODO + const std::size_t start = out.size(); + + write_hex(val, false, sizeof(void*) * 2); + + const std::size_t size2 = out.size() - start; + + if (size2 < ctx.width) + { + // Add padding if necessary + out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' '); + } + src.skip(ctx.args); ctx = {0}; break; @@ -395,19 +567,26 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) case 'g': case 'G': { - if (!src.test()) + if (UNLIKELY(!src.test(ctx.args) || ctx.type)) { drop_sequence(); break; } - if (ctx.type) + // Fallback (TODO) + + const std::string _fmt(fmt - ctx.size, fmt); + + const u64 arg0 = src.template get(0); + const u64 arg1 = ctx.args >= 1 ? src.template get(1) : 0; + const u64 arg2 = ctx.args >= 2 ? src.template get(2) : 0; + + if (const std::size_t _size = std::snprintf(0, 0, _fmt.c_str(), arg0, arg1, arg2)) { - drop_sequence(); - break; + out.resize(out.size() + _size); + std::snprintf(&out.front() + out.size() - _size, _size + 1, _fmt.c_str(), arg0, arg1, arg2); } - fallback(); // TODO src.skip(ctx.args); ctx = {0}; break; @@ -427,5 +606,5 @@ Size cfmt_append(std::string& out, const char* fmt, Src&& src) fmt--, drop_sequence(); } - return static_cast(out.size() - old_size); + return out.size() - start_pos; } diff --git a/rpcs3/Gui/ConLogFrame.cpp b/rpcs3/Gui/ConLogFrame.cpp index 9525e53bbd..7cef833cfe 100644 --- a/rpcs3/Gui/ConLogFrame.cpp +++ b/rpcs3/Gui/ConLogFrame.cpp @@ -46,16 +46,18 @@ struct gui_listener : logs::listener delete read; } - void log(const logs::message& msg) + void log(const logs::message& msg, const std::string& prefix, const std::string& text) { if (msg.sev <= enabled) { const auto _new = new packet; _new->sev = msg.sev; - if (msg.prefix_size > 0) + if (prefix.size() > 0) { - _new->msg = fmt::format("{%s} ", msg.prefix); + _new->msg += "{"; + _new->msg += prefix; + _new->msg += "} "; } if (msg.ch->name) @@ -68,7 +70,7 @@ struct gui_listener : logs::listener _new->msg += "TODO: "; } - _new->msg += msg.text; + _new->msg += text; _new->msg += '\n'; last = last->next = _new;