Re: [dev] key-value config reader
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