diff --git a/renderdoc/common/formatting.h b/renderdoc/common/formatting.h index 9637154b0..5f1cf1ffc 100644 --- a/renderdoc/common/formatting.h +++ b/renderdoc/common/formatting.h @@ -38,8 +38,9 @@ struct Args virtual unsigned int get_uint() = 0; virtual double get_double() = 0; virtual void *get_ptr() = 0; + virtual const char *get_str() = 0; virtual uint64_t get_uint64() = 0; - virtual size_t get_size() = 0; + size_t get_size() { return sizeof(size_t) == 8 ? (size_t)get_uint64() : get_uint(); } }; rdcstr Fmt(const char *format, ...); diff --git a/renderdoc/driver/vulkan/vk_shader_feedback.cpp b/renderdoc/driver/vulkan/vk_shader_feedback.cpp index 5b1374653..72609414e 100644 --- a/renderdoc/driver/vulkan/vk_shader_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_shader_feedback.cpp @@ -145,6 +145,11 @@ public: m_Idx++; return NULL; } + const char *get_str() override + { + m_Idx++; + return NULL; + } uint64_t get_uint64() override { uint64_t ret = *(uint64_t *)m_Cur; @@ -153,7 +158,6 @@ public: return ret; } - size_t get_size() override { return sizeof(size_t) == 8 ? (size_t)get_uint64() : get_uint(); } rdcstr get_error() { return m_Error; } private: const uint32_t *m_Cur; diff --git a/renderdoc/strings/utf8printf.cpp b/renderdoc/strings/utf8printf.cpp index 65c67d488..4c0b5d9ca 100644 --- a/renderdoc/strings/utf8printf.cpp +++ b/renderdoc/strings/utf8printf.cpp @@ -157,9 +157,12 @@ struct FormatterParams int Precision; LengthModifier Length; - static const int NoWidth = -1; // can't set negative width, so -1 indicates no width specified - static const int NoPrecision = - -1; // can't set negative precision, so -1 indicates no precision specified + // can't set negative width, so -1 indicates no width specified + static const int NoWidth = -1; + // can't set negative precision, so -1 indicates no precision specified + static const int NoPrecision = -1; + // VarArgs precision - for %.*s strings + static const int VarPrecision = -2; }; /////////////////////////////////////////////////////////////////////////////// @@ -1447,6 +1450,11 @@ inline void *custom_arg_getter::get_next() return formatter.get_ptr(); } template <> +inline const char *custom_arg_getter::get_next() +{ + return formatter.get_str(); +} +template <> inline uint64_t custom_arg_getter::get_next() { return formatter.get_uint64(); @@ -1589,10 +1597,10 @@ int utf8print_template(char *buf, size_t bufsize, const char *fmt, arg_getter ar { iter++; - // note standard printf supports * here to read precision from a vararg if(*iter == '*') { - RDCDUMPMSG("Unexpected character * expecting precision"); + formatter.Precision = FormatterParams::VarPrecision; + iter++; } // if there's no value for the precision, it is 0 else if(*iter < '0' || *iter > '9') @@ -1676,11 +1684,19 @@ int utf8print_template(char *buf, size_t bufsize, const char *fmt, arg_getter ar int *i = (int *)arg; *i = args.template get_next(); } - else if(type == 's' || type == 'p') + else if(type == 'p') { void **p = (void **)arg; *p = args.template get_next(); } + else if(type == 's') + { + if(formatter.Precision == FormatterParams::VarPrecision) + formatter.Precision = (int)args.template get_next(); + + const char **p = (const char **)arg; + *p = args.template get_next(); + } else if(type == 'e' || type == 'E' || type == 'f' || type == 'F' || type == 'g' || type == 'G' || type == 'a' || type == 'A') { @@ -2006,6 +2022,12 @@ TEST_CASE("utf8printf standard string formatters", "[utf8printf]") // these string constants take 2 bytes for each code point in UTF-8, so it's 8 bytes for 4 chars CHECK(StringFormat::Fmt("%.4s", s.c_str()) == s.substr(0, 8)); CHECK(StringFormat::Fmt("%.4ls", ws.c_str()) == s.substr(0, 8)); + + CHECK(StringFormat::Fmt("%.*s", 4, "foobar") == "foob"); + CHECK(StringFormat::Fmt("%.*ls", 4, L"foobar") == "foob"); + + CHECK(StringFormat::Fmt("%10.*s", 4, "foobar") == " foob"); + CHECK(StringFormat::Fmt("%-10.*s", 4, "foobar") == "foob "); }; };