Optimize str_format(…, …, "%d", …) using templates

This would make the function `str_from_int` unnecessary, at least
user-facing.

Advantage: User doesn't have to care about `str_from_int`/`str_format`
distinction.

Disadvantage: We're adding some template programming to `system.h`,
potentially slowing all compilation.
This commit is contained in:
heinrich5991 2024-05-14 10:17:02 +02:00
parent 392fc0ba9a
commit df9980ee3e
3 changed files with 42 additions and 16 deletions

View file

@ -319,7 +319,11 @@ if(NOT MSVC AND NOT HAIKU)
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-psabi) # parameter passing for argument of type __gnu_cxx::__normal_iterator<CCommandProcessorFragment_Vulkan::SMemoryBlock<1>*, std::vector<CCommandProcessorFragment_Vulkan::SMemoryBlock<1>, std::allocator<CCommandProcessorFragment_Vulkan::SMemoryBlock<1> > > > changed in GCC 7.1
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-unused-parameter)
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-missing-field-initializers)
if(CMAKE_BUILD_TYPE STREQUAL DEBUG)
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wformat=2) # Warn about format strings.
else()
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-format) # Don't warn about format strings in release mode since our `str_format` optimization is incompatible with it.
endif()
add_c_compiler_flag_if_supported(OUR_FLAGS_DEP -Wno-implicit-function-declaration)
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-nullability-completeness) # Mac OS build on github
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wduplicated-cond)

View file

@ -2784,6 +2784,15 @@ int str_format_v(char *buffer, int buffer_size, const char *format, va_list args
return str_utf8_fix_truncation(buffer);
}
int str_format_int(char *buffer, size_t buffer_size, int value)
{
buffer[0] = '\0'; // Fix false positive clang-analyzer-core.UndefinedBinaryOperatorResult when using result
auto result = std::to_chars(buffer, buffer + buffer_size - 1, value);
result.ptr[0] = '\0';
return result.ptr - buffer;
}
#undef str_format
int str_format(char *buffer, int buffer_size, const char *format, ...)
{
va_list args;
@ -2792,6 +2801,9 @@ int str_format(char *buffer, int buffer_size, const char *format, ...)
va_end(args);
return length;
}
#if !defined(CONF_DEBUG)
#define str_format str_format_opt
#endif
const char *str_trim_words(const char *str, int words)
{
@ -3639,13 +3651,6 @@ bool str_tofloat(const char *str, float *out)
return true;
}
void str_from_int(int value, char *buffer, size_t buffer_size)
{
buffer[0] = '\0'; // Fix false positive clang-analyzer-core.UndefinedBinaryOperatorResult when using result
auto result = std::to_chars(buffer, buffer + buffer_size - 1, value);
result.ptr[0] = '\0';
}
int str_utf8_comp_nocase(const char *a, const char *b)
{
int code_a;

View file

@ -1229,6 +1229,31 @@ int str_format_v(char *buffer, int buffer_size, const char *format, va_list args
int str_format(char *buffer, int buffer_size, const char *format, ...)
GNUC_ATTRIBUTE((format(printf, 3, 4)));
#if !defined(CONF_DEBUG)
int str_format_int(char *buffer, size_t buffer_size, int value);
template<typename... Args>
int str_format_opt(char *buffer, int buffer_size, const char *format, Args... args)
{
return str_format(buffer, buffer_size, format, args...);
}
template<>
inline int str_format_opt(char *buffer, int buffer_size, const char *format, int val)
{
if(strcmp(format, "%d") == 0)
{
return str_format_int(buffer, buffer_size, val);
}
else
{
return str_format(buffer, buffer_size, format, val);
}
}
#define str_format str_format_opt
#endif
/**
* Trims specific number of words at the start of a string.
*
@ -2098,14 +2123,6 @@ int64_t str_toint64_base(const char *str, int base = 10);
float str_tofloat(const char *str);
bool str_tofloat(const char *str, float *out);
void str_from_int(int value, char *buffer, size_t buffer_size);
template<size_t N>
void str_from_int(int value, char (&dst)[N])
{
str_from_int(value, dst, N);
}
/**
* Determines whether a character is whitespace.
*