On 2019-05-12, Markus Wichmann <nullp...@gmx.net> wrote:
> On Sat, May 11, 2019 at 08:52:32PM +0100, Piotr Oleskiewicz wrote:
>> I would prefer to
>> write
>>
>>      X(int, i, 1)
>>
>> rather than
>>
>>      X(int, i, atoi, "%d", 1)
>>
>> Many thanks,
>> Piotr
>>
>
> That is going to be tough, as in C in a macro, there is no way to really
> determine what type name you were given. The only thing standard C has
> to offer to help is "sizeof", but that doesn't help you, obviously.
> (sizeof(float) == sizeof(int)).

What about _Generic in C11? This allows you to choose an expression
based on the type of another expression.

So I think something like the following should work:

diff --git a/kv.h b/kv.h
index 4a0be52..57facce 100644
--- a/kv.h
+++ b/kv.h
@@ -23,7 +23,7 @@ atoc(char *str) {
        return strlen(str) > 0 ? str[0] : '\0';
 }

-#define X(type, name, parse, format, init) \
+#define X(type, name, init) \
        type name;
 typedef struct {
        KV
@@ -33,7 +33,7 @@ typedef struct {
 kv
 kv_init() {
        kv c;
-#define X(type, name, parse, format, init) \
+#define X(type, name, init) \
        c.name = init;
        KV
 #undef X
@@ -42,8 +42,13 @@ kv_init() {

 void
 kv_print(FILE *f, kv c) {
-#define X(type, name, parse, format, init) \
-       fprintf(f, "%s = "format"\n", #name, c.name);
+#define X(type, name, init) \
+       fprintf(f, _Generic((type){0}, \
+               char *: "%s = %s\n", \
+               double: "%s = %f\n", \
+               int: "%s = %d\n", \
+               bool: "%s = %d\n" \
+               ), #name, c.name);
        KV
 #undef X
 }
@@ -51,9 +56,14 @@ kv_print(FILE *f, kv c) {
 void
 kv_read(FILE *f, kv *c) {
        char k[MAXLEN], v[MAXLEN];
-#define X(type, name, parse, format, init) \
+#define X(type, name, init) \
        if(strncmp(k, #name, MAX(strlen(k), strlen(#name))) == 0) \
-               c->name = parse(v);
+               c->name = _Generic((type){0}, \
+                       char *: strdup, \
+                       double: atof, \
+                       int: atoi, \
+                       bool: atob \
+                       )(v);
        while(fscanf(f, "%s = %s\n", k, v) == 2) {
                KV
        }

Reply via email to