diff --git a/CMakeLists.txt b/CMakeLists.txt index b0cc64c7..1c81eee4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -542,7 +542,7 @@ if(FMT_C_API) enable_language(C) - add_library(fmt_c STATIC src/c.cc) + add_library(fmt_c STATIC src/fmt-c.cc) target_compile_features(fmt_c PUBLIC cxx_std_11) target_compile_definitions(fmt_c PUBLIC FMT_C_STATIC) @@ -569,7 +569,7 @@ if(FMT_C_API) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) - install(FILES include/fmt/c.h + install(FILES include/fmt/fmt-c.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fmt ) endif() diff --git a/include/fmt/c.h b/include/fmt/fmt-c.h similarity index 90% rename from include/fmt/c.h rename to include/fmt/fmt-c.h index 16ddecc1..50720c5f 100644 --- a/include/fmt/c.h +++ b/include/fmt/fmt-c.h @@ -1,6 +1,9 @@ #ifndef FMT_C_API_H #define FMT_C_API_H +#include +#include +#include #include #define FMT_C_ABI_VERSION 1 @@ -10,14 +13,10 @@ #define FMT_ERR_NULL_FORMAT -1 #define FMT_ERR_EXCEPTION -2 #define FMT_ERR_MEMORY -3 +#define FMT_ERR_INVALID_ARG -4 #ifdef __cplusplus -# include -# include extern "C" { -#else -# include -# include #endif #if defined(_WIN32) && !defined(FMT_C_STATIC) @@ -76,10 +75,6 @@ typedef struct { FMT_C_API int fmt_c_format(char* buffer, size_t capacity, const char* format_str, const FmtArg* args, size_t arg_count); -FMT_C_API void fmt_c_print(FILE* f, const char* format_str, const FmtArg* args, - size_t arg_count); - -FMT_C_API const char* fmt_c_get_error(void); FMT_C_API int fmt_c_get_version(void); @@ -257,19 +252,12 @@ static inline FmtArg fmt_identity(FmtArg x) { return x; } # define FMT_MAP(f, ...) \ FMT_CAT(FMT_MAP_, FMT_NARG(__VA_ARGS__))(f, ##__VA_ARGS__) -# define fmt_snprintf(buf, cap, fmt, ...) \ +# define fmt_format(buf, cap, fmt, ...) \ fmt_c_format( \ buf, cap, fmt, \ (FmtArg[]){{FMT_INT}, FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__)} + 1, \ FMT_NARG(__VA_ARGS__)) -# define fmt_fprintf(f, fmt, ...) \ - fmt_c_print( \ - f, fmt, \ - (FmtArg[]){{FMT_INT}, FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__)} + 1, \ - FMT_NARG(__VA_ARGS__)) - -# define fmt_printf(fmt, ...) fmt_fprintf(stdout, fmt, ##__VA_ARGS__) #endif // !__cplusplus diff --git a/src/c.cc b/src/c.cc deleted file mode 100644 index bdeef210..00000000 --- a/src/c.cc +++ /dev/null @@ -1,241 +0,0 @@ -#undef FMT_C_EXPORT -#define FMT_C_EXPORT -#include "fmt/c.h" - -#include - -#include -#include -#include -#include - -static const size_t MAX_PACKED_ARGS = FMT_C_MAX_ARGS; - -extern "C" { -static thread_local std::string g_last_error; - -const char* fmt_c_get_error(void) { - return g_last_error.empty() ? "" : g_last_error.c_str(); -} - -static void set_error(const char* msg) { - try { - g_last_error = msg; - } catch (...) { - } -} - -static void clear_error() { g_last_error.clear(); } - -int fmt_c_get_version(void) { return FMT_C_ABI_VERSION; } - -using Context = fmt::format_context; - -// Fixed-size array for type-erased format arguments -static thread_local std::array, MAX_PACKED_ARGS> - g_fixed_store; - -static bool populate_store(const FmtArg* c_args, size_t arg_count, - std::vector& custom_buffers) { - if (arg_count > MAX_PACKED_ARGS) { - set_error("Argument count exceeds maximum (FMT_C_MAX_ARGS)"); - return false; - } - - for (size_t i = 0; i < arg_count; ++i) { - switch (c_args[i].type) { - case FMT_INT: - g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.i64); - break; - - case FMT_UINT: - g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.u64); - break; - - case FMT_FLOAT: - g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.f32); - break; - - case FMT_DOUBLE: - g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.f64); - break; - - case FMT_LONG_DOUBLE: - g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.f128); - break; - - case FMT_PTR: - g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.ptr); - break; - - case FMT_CHAR: - g_fixed_store[i] = fmt::basic_format_arg( - static_cast(c_args[i].value.char_val)); - break; - - case FMT_BOOL: - g_fixed_store[i] = - fmt::basic_format_arg(c_args[i].value.bool_val != 0); - break; - - case FMT_STRING: { - const char* s = c_args[i].value.str ? c_args[i].value.str : "(null)"; - g_fixed_store[i] = fmt::basic_format_arg(fmt::string_view(s)); - break; - } - - case FMT_CUSTOM: { - if (!c_args[i].custom_fn) { - set_error("Custom formatter function is NULL"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } - - if (!c_args[i].value.ptr) { - set_error("Custom formatter data pointer is NULL"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } - - try { - std::string buf; - buf.resize(64); // intial bufffer size .... - int len = c_args[i].custom_fn(&buf[0], buf.size(), c_args[i].value.ptr); - - if (len < 0) { - set_error("Custom formatter returned error code"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } - if (static_cast(len) >= buf.size()) { - buf.resize(len + 1); - len = c_args[i].custom_fn(&buf[0], buf.size(), c_args[i].value.ptr); - - if (len < 0) { - set_error("Custom formatter failed on second call"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } - } - - buf.resize(len); - custom_buffers.push_back(std::move(buf)); - g_fixed_store[i] = fmt::basic_format_arg( - fmt::string_view(custom_buffers.back())); - - } catch (const std::bad_alloc&) { - set_error("Memory allocation failed in custom formatter"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } catch (...) { - set_error("Unknown exception in custom formatter"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } - break; - } - - default: - set_error("Unknown FmtType enum value"); - g_fixed_store[i] = - fmt::basic_format_arg(fmt::string_view("")); - return false; - } - } - - return true; -} -int fmt_c_format(char* buffer, size_t capacity, const char* format_str, - const FmtArg* args, size_t arg_count) { - clear_error(); - if (!format_str) { - set_error("Format string is NULL"); - return FMT_ERR_NULL_FORMAT; - } - - if (arg_count > MAX_PACKED_ARGS) { - set_error("Too many arguments (maximum is FMT_C_MAX_ARGS)"); - return FMT_ERR_MEMORY; - } - - try { - std::vector custom_buffers; - if (arg_count > 0) { - if (!args) { - set_error("Argument array is NULL but arg_count > 0"); - return FMT_ERR_NULL_FORMAT; - } - if (!populate_store(args, arg_count, custom_buffers)) { - return FMT_ERR_EXCEPTION; - } - } - - auto format_args_view = fmt::basic_format_args( - g_fixed_store.data(), static_cast(arg_count)); - - if (!buffer || capacity == 0) { - char tmp[1]; - auto result = fmt::vformat_to_n(tmp, 0, format_str, format_args_view); - return static_cast(result.size); - } - auto result = - fmt::vformat_to_n(buffer, capacity - 1, format_str, format_args_view); - - *result.out = '\0'; - return static_cast(result.size); - } catch (const std::exception& e) { - set_error(e.what()); - return FMT_ERR_EXCEPTION; - } catch (...) { - set_error("Unknown C++ exception"); - return FMT_ERR_EXCEPTION; - } -} - -void fmt_c_print(FILE* f, const char* format_str, const FmtArg* args, - size_t arg_count) { - clear_error(); - - if (!f) { - set_error("File stream is NULL"); - return; - } - - if (!format_str) { - set_error("Format string is NULL"); - return; - } - if (arg_count > MAX_PACKED_ARGS) { - set_error("Too many arguments (maximum is FMT_C_MAX_ARGS)"); - return; - } - - try { - std::vector custom_buffers; - if (arg_count > 0) { - if (!args) { - set_error("Argument array is NULL but arg_count > 0"); - return; - } - if (!populate_store(args, arg_count, custom_buffers)) { - return; - } - } - auto format_args_view = fmt::basic_format_args( - g_fixed_store.data(), static_cast(arg_count)); - fmt::vprint(f, format_str, format_args_view); - - } catch (const std::exception& e) { - set_error(e.what()); - } catch (...) { - set_error("Unknown C++ exception"); - } -} - -} // extern "C" \ No newline at end of file diff --git a/src/fmt-c.cc b/src/fmt-c.cc new file mode 100644 index 00000000..4b7dd031 --- /dev/null +++ b/src/fmt-c.cc @@ -0,0 +1,134 @@ +#undef FMT_C_EXPORT +#define FMT_C_EXPORT +#include "fmt/fmt-c.h" + +#include + +#include +#include +#include +#include + + +extern "C" { + +int fmt_c_get_version(void) { return FMT_C_ABI_VERSION; } + +using Context = fmt::format_context; + +// Fixed-size array for type-erased format arguments +static thread_local std::array, FMT_C_MAX_ARGS> + g_fixed_store; + +static bool populate_store(const FmtArg* c_args, size_t arg_count, + std::vector& custom_buffers) { + if (arg_count > FMT_C_MAX_ARGS) { + return false; + } + + for (size_t i = 0; i < arg_count; ++i) { + switch (c_args[i].type) { + case FMT_INT: + g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.i64); + break; + case FMT_UINT: + g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.u64); + break; + case FMT_FLOAT: + g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.f32); + break; + case FMT_DOUBLE: + g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.f64); + break; + case FMT_LONG_DOUBLE: + g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.f128); + break; + case FMT_PTR: + g_fixed_store[i] = fmt::basic_format_arg(c_args[i].value.ptr); + break; + case FMT_CHAR: + g_fixed_store[i] = fmt::basic_format_arg( + static_cast(c_args[i].value.char_val)); + break; + case FMT_BOOL: + g_fixed_store[i] = + fmt::basic_format_arg(c_args[i].value.bool_val != 0); + break; + case FMT_STRING: { + const char* s = c_args[i].value.str ? c_args[i].value.str : "(null)"; + g_fixed_store[i] = fmt::basic_format_arg(fmt::string_view(s)); + break; + } + + case FMT_CUSTOM: { + if (!c_args[i].custom_fn || !c_args[i].value.ptr) { + g_fixed_store[i] = fmt::basic_format_arg(fmt::string_view("")); + return false; + } + + try { + std::string buf; + buf.resize(64); + int len = c_args[i].custom_fn(&buf[0], buf.size(), c_args[i].value.ptr); + + if (len < 0) return false; + + if (static_cast(len) >= buf.size()) { + buf.resize(len + 1); + len = c_args[i].custom_fn(&buf[0], buf.size(), c_args[i].value.ptr); + if (len < 0) return false; + } + + buf.resize(len); + custom_buffers.push_back(std::move(buf)); + g_fixed_store[i] = fmt::basic_format_arg( + fmt::string_view(custom_buffers.back())); + + } catch (...) { + return false; + } + break; + } + + default: + return false; + } + } + return true; +} +int fmt_c_format(char* buffer, size_t capacity, const char* format_str, + const FmtArg* args, size_t arg_count) { + if (!format_str) return FMT_ERR_NULL_FORMAT; + if (arg_count > FMT_C_MAX_ARGS) return FMT_ERR_INVALID_ARG; + + try { + std::vector custom_buffers; + if (arg_count > 0) { + if (!args) return FMT_ERR_INVALID_ARG; + if (!populate_store(args, arg_count, custom_buffers)) { + return FMT_ERR_EXCEPTION; + } + } + + auto format_args_view = fmt::basic_format_args( + g_fixed_store.data(), static_cast(arg_count)); + + if (!buffer || capacity == 0) { + char tmp[1]; + auto result = fmt::vformat_to_n(tmp, 0, format_str, format_args_view); + return static_cast(result.size); + } + + auto result = fmt::vformat_to_n(buffer, capacity - 1, format_str, format_args_view); + *result.out = '\0'; + return static_cast(result.size); + + } catch (const std::bad_alloc&) { + return FMT_ERR_MEMORY; + } catch (...) { + return FMT_ERR_EXCEPTION; + } +} + + +} // extern "C" \ No newline at end of file diff --git a/test/test_c.c b/test/test_c.c index 697026ef..51f8fd32 100644 --- a/test/test_c.c +++ b/test/test_c.c @@ -3,7 +3,7 @@ #include #include -#include "fmt/c.h" +#include "fmt/fmt-c.h" #define TEST(name) \ static void test_##name(void); \ @@ -43,41 +43,41 @@ TEST(basic_integer) { char buf[100]; - int ret = fmt_snprintf(buf, sizeof(buf), "Number: {}", 42); + int ret = fmt_format(buf, sizeof(buf), "Number: {}", 42); ASSERT_STR_EQ(buf, "Number: 42"); ASSERT_INT_EQ(ret, 10); } TEST(multiple_integers) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{} + {} = {}", 1, 2, 3); + fmt_format(buf, sizeof(buf), "{} + {} = {}", 1, 2, 3); ASSERT_STR_EQ(buf, "1 + 2 = 3"); } TEST(unsigned_integers) { char buf[100]; unsigned int x = 4294967295U; - fmt_snprintf(buf, sizeof(buf), "{}", x); + fmt_format(buf, sizeof(buf), "{}", x); ASSERT_STR_EQ(buf, "4294967295"); } TEST(floating_point) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "Pi = {}", 3.14159); + fmt_format(buf, sizeof(buf), "Pi = {}", 3.14159); ASSERT_TRUE(strncmp(buf, "Pi = 3.14159", 12) == 0); } TEST(float_type) { char buf[100]; float f = 1.234f; - fmt_snprintf(buf, sizeof(buf), "Float: {:.3f}", f); + fmt_format(buf, sizeof(buf), "Float: {:.3f}", f); ASSERT_STR_EQ(buf, "Float: 1.234"); } TEST(long_double_type) { char buf[100]; long double ld = 12345.6789L; - fmt_snprintf(buf, sizeof(buf), "{:.4f}", ld); + fmt_format(buf, sizeof(buf), "{:.4f}", ld); ASSERT_STR_EQ(buf, "12345.6789"); } @@ -87,45 +87,45 @@ TEST(mixed_floating_types) { double d = 2.5; long double ld = 3.5L; - fmt_snprintf(buf, sizeof(buf), "{} {} {}", f, d, ld); + fmt_format(buf, sizeof(buf), "{} {} {}", f, d, ld); ASSERT_STR_EQ(buf, "1.5 2.5 3.5"); } TEST(strings) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "Hello, {}!", "from fmt!"); + fmt_format(buf, sizeof(buf), "Hello, {}!", "from fmt!"); ASSERT_STR_EQ(buf, "Hello, from fmt!!"); } TEST(null_string) { char buf[100]; const char* null_str = NULL; - fmt_snprintf(buf, sizeof(buf), "{}", null_str); + fmt_format(buf, sizeof(buf), "{}", null_str); ASSERT_STR_EQ(buf, "(null)"); } TEST(pointers) { char buf[100]; void* ptr = (void*)0x12345678; - fmt_snprintf(buf, sizeof(buf), "{}", ptr); + fmt_format(buf, sizeof(buf), "{}", ptr); ASSERT_TRUE(strstr(buf, "12345678") != NULL); } TEST(booleans) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{} {}", (bool)true, (bool)false); + fmt_format(buf, sizeof(buf), "{} {}", (bool)true, (bool)false); ASSERT_STR_EQ(buf, "true false"); } TEST(characters) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "Char: {}", (char)'A'); + fmt_format(buf, sizeof(buf), "Char: {}", (char)'A'); ASSERT_STR_EQ(buf, "Char: A"); } TEST(mixed_types) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{} {} {} {}", 42, 3.14, "text", (bool)true); + fmt_format(buf, sizeof(buf), "{} {} {} {}", 42, 3.14, "text", (bool)true); ASSERT_TRUE(strstr(buf, "42") != NULL); ASSERT_TRUE(strstr(buf, "3.14") != NULL); ASSERT_TRUE(strstr(buf, "text") != NULL); @@ -134,51 +134,50 @@ TEST(mixed_types) { TEST(format_zero_padding) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{:05d}", 42); + fmt_format(buf, sizeof(buf), "{:05d}", 42); ASSERT_STR_EQ(buf, "00042"); } TEST(format_precision) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{:.2f}", 3.14159); + fmt_format(buf, sizeof(buf), "{:.2f}", 3.14159); ASSERT_STR_EQ(buf, "3.14"); } TEST(format_hex) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{:x}", 255); + fmt_format(buf, sizeof(buf), "{:x}", 255); ASSERT_STR_EQ(buf, "ff"); } TEST(format_hex_upper) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{:X}", 255); + fmt_format(buf, sizeof(buf), "{:X}", 255); ASSERT_STR_EQ(buf, "FF"); } TEST(positional_arguments) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{1} {0}", "from fmt!", "Hello"); + fmt_format(buf, sizeof(buf), "{1} {0}", "from fmt!", "Hello"); ASSERT_STR_EQ(buf, "Hello from fmt!"); } TEST(zero_arguments) { char buf[100]; - // fmt_snprintf(buf, sizeof(buf), "No arguments"); + // fmt_format(buf, sizeof(buf), "No arguments"); fmt_c_format(buf, sizeof(buf), "No arguments", NULL, - 0); // strict compiler check bypass - either turn on cextension - // in cmake or this + 0); // strict compiler check bypass ASSERT_STR_EQ(buf, "No arguments"); } TEST(buffer_size_query) { - int size = fmt_snprintf(NULL, 0, "Test string: {}", 42); + int size = fmt_format(NULL, 0, "Test string: {}", 42); ASSERT_INT_EQ(size, 15); } TEST(buffer_overflow) { char buf[10]; - int ret = fmt_snprintf(buf, sizeof(buf), "Very long string: {}", 12345); + int ret = fmt_format(buf, sizeof(buf), "Very long string: {}", 12345); ASSERT_INT_EQ(buf[9], '\0'); ASSERT_TRUE(ret > 9); } @@ -205,8 +204,7 @@ TEST(custom_formatter_null_function) { FmtArg args[] = {fmt_from_custom(&data, NULL)}; int ret = fmt_c_format(buf, sizeof(buf), "Value: {}", args, 1); ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strstr(err, "NULL") != NULL); + // ASSERT_INT_EQ(ret, FMT_ERR_EXCEPTION); // Optional specific check } TEST(custom_formatter_null_data) { @@ -214,8 +212,6 @@ TEST(custom_formatter_null_data) { FmtArg args[] = {fmt_from_custom(NULL, custom_point_formatter)}; int ret = fmt_c_format(buf, sizeof(buf), "Value: {}", args, 1); ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strstr(err, "NULL") != NULL); } static int failing_formatter(char* buf, size_t cap, const void* data) { @@ -231,16 +227,12 @@ TEST(custom_formatter_error_return) { FmtArg args[] = {FMT_MAKE_CUSTOM(&data, failing_formatter)}; int ret = fmt_c_format(buf, sizeof(buf), "Value: {}", args, 1); ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strstr(err, "error") != NULL); } TEST(error_null_format) { char buf[100]; int ret = fmt_c_format(buf, sizeof(buf), NULL, NULL, 0); - ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strlen(err) > 0); + ASSERT_INT_EQ(ret, FMT_ERR_NULL_FORMAT); } TEST(error_too_many_args) { @@ -250,44 +242,19 @@ TEST(error_too_many_args) { args[i] = fmt_from_int(i); } int ret = fmt_c_format(buf, sizeof(buf), "{}", args, 20); - ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strstr(err, "maximum") != NULL || strstr(err, "many") != NULL); + ASSERT_INT_EQ(ret, FMT_ERR_INVALID_ARG); } -// NEW: Test NULL args with non-zero count TEST(error_null_args_nonzero_count) { char buf[100]; int ret = fmt_c_format(buf, sizeof(buf), "{}", NULL, 1); - ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strlen(err) > 0); + ASSERT_INT_EQ(ret, FMT_ERR_INVALID_ARG); } TEST(error_invalid_format) { char buf[100]; - int ret = fmt_snprintf(buf, sizeof(buf), "{:invalid}", 1); + int ret = fmt_format(buf, sizeof(buf), "{:invalid}", 1); ASSERT_TRUE(ret < 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strlen(err) > 0); -} - -TEST(printf_to_stdout) { - printf("\n Output from fmt_printf: "); - fmt_printf("Test {} {} {}", 1, 2.5, "string"); - printf("\n"); -} -TEST(print_null_file) { - FmtArg args[] = {fmt_from_int(42)}; - fmt_c_print(NULL, "{}", args, 1); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strstr(err, "NULL") != NULL); -} - -TEST(print_null_format) { - fmt_c_print(stdout, NULL, NULL, 0); - const char* err = fmt_c_get_error(); - ASSERT_TRUE(strstr(err, "NULL") != NULL); } TEST(long_strings) { @@ -295,26 +262,26 @@ TEST(long_strings) { const char* long_str = "This is a very long string that contains a lot of text " "to test the buffer handling capabilities of the formatter"; - fmt_snprintf(buf, sizeof(buf), "Message: {}", long_str); + fmt_format(buf, sizeof(buf), "Message: {}", long_str); ASSERT_TRUE(strstr(buf, long_str) != NULL); } TEST(multiple_calls) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{} {}", 1, 2); + fmt_format(buf, sizeof(buf), "{} {}", 1, 2); ASSERT_STR_EQ(buf, "1 2"); - fmt_snprintf(buf, sizeof(buf), "{} {}", "hello", 3.14); + fmt_format(buf, sizeof(buf), "{} {}", "hello", 3.14); ASSERT_TRUE(strstr(buf, "hello") != NULL); - fmt_snprintf(buf, sizeof(buf), "{}", (bool)true); + fmt_format(buf, sizeof(buf), "{}", (bool)true); ASSERT_STR_EQ(buf, "true"); } TEST(escaped_braces) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{{}} {}", 42); + fmt_format(buf, sizeof(buf), "{{}} {}", 42); ASSERT_STR_EQ(buf, "{} 42"); } @@ -329,7 +296,7 @@ TEST(all_integer_types) { unsigned long ul = 700UL; unsigned long long ull = 800ULL; - fmt_snprintf(buf, sizeof(buf), "{} {} {} {} {} {} {} {}", s, i, l, ll, us, ui, + fmt_format(buf, sizeof(buf), "{} {} {} {} {} {} {} {}", s, i, l, ll, us, ui, ul, ull); ASSERT_TRUE(strstr(buf, "100") != NULL); ASSERT_TRUE(strstr(buf, "800") != NULL); @@ -342,21 +309,19 @@ TEST(version_check) { TEST(alignment) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{:>10}", 42); + fmt_format(buf, sizeof(buf), "{:>10}", 42); ASSERT_STR_EQ(buf, " 42"); } TEST(center_alignment) { char buf[100]; - fmt_snprintf(buf, sizeof(buf), "{:^10}", "Hi"); + fmt_format(buf, sizeof(buf), "{:^10}", "Hi"); ASSERT_STR_EQ(buf, " Hi "); } TEST(struct_size_and_alignment) { // Verify that FmtArg has expected size with explicit padding - // On 64-bit: 4 (type) + 4 (padding) + 16 (union) + 8 (ptr) = 32 bytes .... 24 - // bytes in MSVC becuz of it's internal optimization This may vary on 32-bit - // or with different compilers + // On 64-bit: 4 (type) + 4 (padding) + 16 (union) + 8 (ptr) = 32 bytes .... printf("\n FmtArg size: %zu bytes (alignment: %zu)\n", sizeof(FmtArg), _Alignof(FmtArg)); @@ -396,9 +361,6 @@ int main(void) { run_test_error_null_format(); run_test_error_too_many_args(); run_test_error_invalid_format(); - run_test_printf_to_stdout(); - run_test_print_null_file(); - run_test_print_null_format(); run_test_long_strings(); run_test_multiple_calls(); run_test_escaped_braces();