mirror of
https://github.com/fmtlib/fmt.git
synced 2026-06-15 08:26:13 +08:00
Add fmt_print to C API (#4789)
* Add FMT_FORMAT_ARGS(fmt, ...) macro to C API to simplify user-defined format wrappers * Add fmt_print to C API
This commit is contained in:
parent
9afcd929ba
commit
ffd8397db1
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h> // bool
|
#include <stdbool.h> // bool
|
||||||
#include <stddef.h> // size_t
|
#include <stddef.h> // size_t
|
||||||
|
#include <stdio.h> // FILE
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -46,6 +47,8 @@ enum { fmt_error = -1, fmt_error_invalid_arg = -2 };
|
|||||||
|
|
||||||
int fmt_vformat(char* buffer, size_t size, const char* fmt, const fmt_arg* args,
|
int fmt_vformat(char* buffer, size_t size, const char* fmt, const fmt_arg* args,
|
||||||
size_t num_args);
|
size_t num_args);
|
||||||
|
int fmt_vprint(FILE* stream, const char* fmt, const fmt_arg* args,
|
||||||
|
size_t num_args);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@ -181,11 +184,17 @@ typedef enum {} fmt_signed_char;
|
|||||||
(fmt_arg[]) { FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__) }
|
(fmt_arg[]) { FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__) }
|
||||||
# define FMT_EXPAND(v) v
|
# define FMT_EXPAND(v) v
|
||||||
|
|
||||||
# define fmt_format(buffer, size, fmt, ...) \
|
# define FMT_FORMAT_ARGS(fmt, ...) \
|
||||||
fmt_vformat((buffer), (size), (fmt), \
|
(fmt), \
|
||||||
FMT_EXPAND(FMT_VA_SELECT(FMT_MAKE_NULL, FMT_MAKE_ARGLIST, \
|
FMT_EXPAND(FMT_VA_SELECT(FMT_MAKE_NULL, FMT_MAKE_ARGLIST, \
|
||||||
##__VA_ARGS__)(__VA_ARGS__)), \
|
##__VA_ARGS__)(__VA_ARGS__)), \
|
||||||
FMT_NARG(, ##__VA_ARGS__))
|
FMT_NARG(, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
# define fmt_format(buffer, size, fmt, ...) \
|
||||||
|
fmt_vformat((buffer), (size), FMT_FORMAT_ARGS((fmt), ##__VA_ARGS__))
|
||||||
|
|
||||||
|
# define fmt_print(stream, fmt, ...) \
|
||||||
|
fmt_vprint((stream), FMT_FORMAT_ARGS((fmt), ##__VA_ARGS__))
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
|||||||
34
src/fmt-c.cc
34
src/fmt-c.cc
@ -9,12 +9,12 @@
|
|||||||
|
|
||||||
#include <fmt/base.h>
|
#include <fmt/base.h>
|
||||||
|
|
||||||
extern "C" int fmt_vformat(char* buffer, size_t size, const char* fmt,
|
constexpr size_t max_c_format_args = 16;
|
||||||
const fmt_arg* args, size_t num_args) {
|
static int convert_c_format_args(
|
||||||
constexpr size_t max_args = 16;
|
fmt::basic_format_arg<fmt::format_context>* format_args,
|
||||||
if (num_args > max_args) return fmt_error_invalid_arg;
|
const fmt_arg* args, size_t num_args) {
|
||||||
|
if (num_args > max_c_format_args) return fmt_error_invalid_arg;
|
||||||
|
|
||||||
fmt::basic_format_arg<fmt::format_context> format_args[max_args];
|
|
||||||
for (size_t i = 0; i < num_args; ++i) {
|
for (size_t i = 0; i < num_args; ++i) {
|
||||||
switch (args[i].type) {
|
switch (args[i].type) {
|
||||||
case fmt_int: format_args[i] = args[i].value.int_value; break;
|
case fmt_int: format_args[i] = args[i].value.int_value; break;
|
||||||
@ -31,6 +31,15 @@ extern "C" int fmt_vformat(char* buffer, size_t size, const char* fmt,
|
|||||||
default: return fmt_error_invalid_arg;
|
default: return fmt_error_invalid_arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int fmt_vformat(char* buffer, size_t size, const char* fmt,
|
||||||
|
const fmt_arg* args, size_t num_args) {
|
||||||
|
fmt::basic_format_arg<fmt::format_context> format_args[max_c_format_args];
|
||||||
|
int error = convert_c_format_args(format_args, args, num_args);
|
||||||
|
if (error != 0) return error;
|
||||||
|
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
auto result = fmt::vformat_to_n(
|
auto result = fmt::vformat_to_n(
|
||||||
buffer, size, fmt,
|
buffer, size, fmt,
|
||||||
@ -40,3 +49,18 @@ extern "C" int fmt_vformat(char* buffer, size_t size, const char* fmt,
|
|||||||
FMT_CATCH(...) {}
|
FMT_CATCH(...) {}
|
||||||
return fmt_error;
|
return fmt_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" int fmt_vprint(FILE* stream, const char* fmt, const fmt_arg* args,
|
||||||
|
size_t num_args) {
|
||||||
|
fmt::basic_format_arg<fmt::format_context> format_args[max_c_format_args];
|
||||||
|
int error = convert_c_format_args(format_args, args, num_args);
|
||||||
|
if (error != 0) return error;
|
||||||
|
|
||||||
|
FMT_TRY {
|
||||||
|
fmt::vprint(stream, fmt,
|
||||||
|
fmt::format_args(format_args, static_cast<int>(num_args)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
FMT_CATCH(...) {}
|
||||||
|
return fmt_error;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user