Add support for varargs length in utf8 printf

This commit is contained in:
baldurk
2025-05-13 12:48:56 +01:00
parent 9fab650555
commit fc9999d67c
3 changed files with 35 additions and 8 deletions
+2 -1
View File
@@ -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, ...);
@@ -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;
+28 -6
View File
@@ -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<void *>()
return formatter.get_ptr();
}
template <>
inline const char *custom_arg_getter::get_next<const char *>()
{
return formatter.get_str();
}
template <>
inline uint64_t custom_arg_getter::get_next<uint64_t>()
{
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<int>();
}
else if(type == 's' || type == 'p')
else if(type == 'p')
{
void **p = (void **)arg;
*p = args.template get_next<void *>();
}
else if(type == 's')
{
if(formatter.Precision == FormatterParams::VarPrecision)
formatter.Precision = (int)args.template get_next<unsigned int>();
const char **p = (const char **)arg;
*p = args.template get_next<const char *>();
}
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 ");
};
};