Skip to content

Commit 60d5d0c

Browse files
committed
Workaround broken _Generic in MSVC
1 parent 9e5bb7e commit 60d5d0c

File tree

2 files changed

+32
-55
lines changed

2 files changed

+32
-55
lines changed

include/fmt/fmt-c.h

Lines changed: 26 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -44,87 +44,66 @@ typedef struct {
4444

4545
enum { fmt_error = -1, fmt_error_invalid_arg = -2 };
4646

47-
int fmt_vformat(char* buffer, size_t size, const char* fmt,
48-
const fmt_arg* args, size_t num_args);
47+
int fmt_vformat(char* buffer, size_t size, const char* fmt, const fmt_arg* args,
48+
size_t num_args);
49+
50+
#ifdef __cplusplus
51+
}
52+
#endif
53+
54+
#ifndef __cplusplus
4955

5056
static inline fmt_arg fmt_from_int(long long x) {
51-
fmt_arg arg;
52-
arg.type = fmt_int;
53-
arg.value.int_value = x;
54-
return arg;
57+
return (fmt_arg){.type = fmt_int, .value.int_value = x};
5558
}
5659

5760
static inline fmt_arg fmt_from_uint(unsigned long long x) {
58-
fmt_arg arg;
59-
arg.type = fmt_uint;
60-
arg.value.uint_value = x;
61-
return arg;
61+
return (fmt_arg){.type = fmt_uint, .value.uint_value = x};
6262
}
6363

6464
static inline fmt_arg fmt_from_bool(bool x) {
65-
fmt_arg arg;
66-
arg.type = fmt_bool;
67-
arg.value.bool_value = x;
68-
return arg;
65+
return (fmt_arg){.type = fmt_bool, .value.bool_value = x};
6966
}
7067

71-
static inline fmt_arg fmt_from_char(int x) {
72-
fmt_arg arg;
73-
arg.type = fmt_char;
74-
arg.value.char_value = x;
75-
return arg;
68+
static inline fmt_arg fmt_from_char(char x) {
69+
return (fmt_arg){.type = fmt_char, .value.char_value = x};
7670
}
7771

7872
static inline fmt_arg fmt_from_float(float x) {
79-
fmt_arg arg;
80-
arg.type = fmt_float;
81-
arg.value.float_value = x;
82-
return arg;
73+
return (fmt_arg){.type = fmt_float, .value.float_value = x};
8374
}
8475

8576
static inline fmt_arg fmt_from_double(double x) {
86-
fmt_arg arg;
87-
arg.type = fmt_double;
88-
arg.value.double_value = x;
89-
return arg;
77+
return (fmt_arg){.type = fmt_double, .value.double_value = x};
9078
}
9179

9280
static inline fmt_arg fmt_from_long_double(long double x) {
93-
fmt_arg arg;
94-
arg.type = fmt_long_double;
95-
arg.value.long_double_value = x;
96-
return arg;
81+
return (fmt_arg){.type = fmt_long_double, .value.long_double_value = x};
9782
}
9883

9984
static inline fmt_arg fmt_from_str(const char* x) {
100-
fmt_arg arg;
101-
arg.type = fmt_cstring;
102-
arg.value.cstring = x;
103-
return arg;
85+
return (fmt_arg){.type = fmt_cstring, .value.cstring = x};
10486
}
10587

10688
static inline fmt_arg fmt_from_ptr(const void* x) {
107-
fmt_arg arg;
108-
arg.type = fmt_pointer;
109-
arg.value.pointer = x;
110-
return arg;
89+
return (fmt_arg){.type = fmt_pointer, .value.pointer = x};
11190
}
11291

113-
#ifdef __cplusplus
114-
}
115-
#endif
116-
117-
#ifndef __cplusplus
118-
11992
void fmt_unsupported_type(void);
12093

94+
# ifndef _MSC_VER
95+
typedef signed char fmt_signed_char;
96+
# else
97+
typedef enum {} fmt_signed_char;
98+
# endif
12199
// Require modern MSVC with conformant preprocessor
122100
# if defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)
123101
# error "C API requires MSVC 2019+ with /Zc:preprocessor flag."
124102
# endif
125103

126104
# define FMT_MAKE_ARG(x) \
127105
_Generic((x), \
106+
fmt_signed_char: fmt_from_int, \
128107
unsigned char: fmt_from_uint, \
129108
short: fmt_from_int, \
130109
unsigned short: fmt_from_uint, \
@@ -189,9 +168,9 @@ void fmt_unsupported_type(void);
189168
# define FMT_MAP(f, ...) \
190169
FMT_CAT(FMT_MAP_, FMT_NARG(__VA_ARGS__))(f, ##__VA_ARGS__)
191170

192-
# define fmt_format(buffer, size, fmt, ...) \
171+
# define fmt_format(buffer, size, fmt, ...) \
193172
fmt_vformat( \
194-
buffer, size, fmt, \
173+
buffer, size, fmt, \
195174
(fmt_arg[]){{fmt_int}, FMT_MAP(FMT_MAKE_ARG, ##__VA_ARGS__)} + 1, \
196175
FMT_NARG(__VA_ARGS__))
197176

src/fmt-c.cc

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,22 @@ extern "C" int fmt_vformat(char* buffer, size_t size, const char* fmt,
1919
switch (args[i].type) {
2020
case fmt_int: format_args[i] = args[i].value.int_value; break;
2121
case fmt_uint: format_args[i] = args[i].value.uint_value; break;
22+
case fmt_bool: format_args[i] = args[i].value.bool_value; break;
23+
case fmt_char: format_args[i] = args[i].value.char_value; break;
2224
case fmt_float: format_args[i] = args[i].value.float_value; break;
2325
case fmt_double: format_args[i] = args[i].value.double_value; break;
2426
case fmt_long_double:
2527
format_args[i] = args[i].value.long_double_value;
2628
break;
27-
case fmt_pointer: format_args[i] = args[i].value.pointer; break;
28-
case fmt_char: format_args[i] = args[i].value.char_value; break;
29-
case fmt_bool: format_args[i] = args[i].value.bool_value; break;
3029
case fmt_cstring: format_args[i] = args[i].value.cstring; break;
30+
case fmt_pointer: format_args[i] = args[i].value.pointer; break;
3131
default: return fmt_error_invalid_arg;
3232
}
3333
}
34-
35-
auto format_args_view = fmt::basic_format_args<fmt::format_context>(
36-
format_args, static_cast<int>(num_args));
37-
3834
try {
39-
auto result = fmt::vformat_to_n(buffer, size, fmt, format_args_view);
35+
auto result = fmt::vformat_to_n(
36+
buffer, size, fmt,
37+
fmt::format_args(format_args, static_cast<int>(num_args)));
4038
return static_cast<int>(result.size);
4139
} catch (...) {
4240
}

0 commit comments

Comments
 (0)