#define _XOPEN_SOURCE #include #include #include #include #include "keyword.h" #include "misc.h" void *get_keyword_offset_ptr(const keyword *key, void *ptr) { char *ret = (char *)(ptr+key->offsets[0]); for (int i = 1; (int64_t)key->offsets[i] >= 0; ++i) { ret = *(char **)(ret+key->offsets[i]); } return (void *)ret; } keyword_val get_keyword_value(const keyword *key, char *value, int *error) { keyword_val val = {0}; int dummy = 0; error = (error != NULL) ? error : &dummy; *error = 0; switch (key->type) { case TYPE_INT : case TYPE_BOOL : val.i = strtol(value, NULL, 0); break; case TYPE_TIME : if (key->time_fmt != NULL) { struct tm tm = {0}; if (strptime(value, key->time_fmt, &tm) != NULL) { tm.tm_isdst = -1; val.t = mktime(&tm); } else { *error = 3; } } else { *error = 4; } break; case TYPE_STRING: val.str = make_str(value); break; case TYPE_FLOAT : val.f = strtof(value, NULL); break; default : *error = 2; break; } return val; } int set_keyword(const keyword *key, keyword_val val, void *ret, void *ctx) { const int callback_ret = (key->callback != NULL) ? key->callback(ctx, ret, key, val) : 0; if (callback_ret < 0 || callback_ret > 0) { return (callback_ret > 0) ? 0 : 5; } else { char *tmp_ret = (char *)get_keyword_offset_ptr(key, ret); switch (key->type) { case TYPE_INT : case TYPE_BOOL : *(int *)tmp_ret = val.i; break; case TYPE_TIME : *(time_t *)tmp_ret = val.t; break; case TYPE_STRING: *(char **)tmp_ret = val.str; break; case TYPE_FLOAT : *(float *)tmp_ret = val.f; break; default : return 6; break; } return 0; } } keyword_val parse_keyword(const keyword *key, char *key_str, char *value, int *error) { int dummy = 0; error = (error != NULL) ? error : &dummy; if (!strcmp(key->key, key_str)) { return get_keyword_value(key, value, error); } else { *error = 1; return (keyword_val){0}; } } int parse_keywords(const keyword **keys, char *key, char *value, void *ret, void *ctx) { keyword_val val = {0}; int error = 0; for (int i = 0; keys[i] != NULL; ++i) { val = parse_keyword(keys[i], key, value, &error); if (!error) { return set_keyword(keys[i], val, ret, ctx); } } return error; }