Re: [dev] key-value config reader

From: Michael Forney <mforney_AT_mforney.org>
Date: Sun, 12 May 2019 01:30:10 -0700

On 2019-05-12, Markus Wichmann <nullplan_AT_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
_AT_@ -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
_AT_@ -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
_AT_@ -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
 }
_AT_@ -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
         }
Received on Sun May 12 2019 - 10:30:10 CEST

This archive was generated by hypermail 2.3.0 : Sun May 12 2019 - 11:00:09 CEST