Skip to content

Commit

Permalink
Add helpers for parsing, copying and freeing config sub-sections
Browse files Browse the repository at this point in the history
CL: Add helpers for parsing, copying and freeing config sub-sections
  • Loading branch information
rojer committed Jan 18, 2020
1 parent a83c1bd commit f39a7df
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 15 deletions.
15 changes: 13 additions & 2 deletions include/mgos_config_util.h
Expand Up @@ -81,8 +81,12 @@ struct mgos_conf_entry {
* checking keys against `acl`.
*/
bool mgos_conf_parse(const struct mg_str json, const char *acl,
const struct mgos_conf_entry *schema, void *cfg);
const struct mgos_conf_entry *schema,
struct mgos_config *cfg);

/*
* Parse a sub-section of the config.
*/
bool mgos_conf_parse_sub(const struct mg_str json,
const struct mgos_conf_entry *sub_schema, void *cfg);

Expand Down Expand Up @@ -119,6 +123,13 @@ bool mgos_conf_emit_f(const void *cfg, const void *base,
const struct mgos_conf_entry *schema, bool pretty,
const char *fname);

/*
* Copies a config struct from src to dst.
* The copy is independent and needs to be freed.
*/
bool mgos_conf_copy(const struct mgos_conf_entry *schema, const void *src,
void *dst);

/*
* Frees any resources allocated in `cfg`.
*/
Expand All @@ -130,7 +141,7 @@ void mgos_conf_free(const struct mgos_conf_entry *schema, void *cfg);
* returns `NULL`.
*/
const struct mgos_conf_entry *mgos_conf_find_schema_entry(
const char *path, const struct mgos_conf_entry *obj);
const char *path, const struct mgos_conf_entry *schema);

/*
* Like `mgos_conf_find_schema_entry()`, but takes the path as a
Expand Down
48 changes: 41 additions & 7 deletions src/mgos_config_util.c
Expand Up @@ -213,7 +213,8 @@ static bool mgos_conf_parse_off(const struct mg_str json, const char *acl,
}

bool mgos_conf_parse(const struct mg_str json, const char *acl,
const struct mgos_conf_entry *schema, void *cfg) {
const struct mgos_conf_entry *schema,
struct mgos_config *cfg) {
return mgos_conf_parse_off(json, acl, schema, 0, cfg);
}

Expand Down Expand Up @@ -259,8 +260,7 @@ static bool mgos_conf_value_eq(const void *cfg, const void *base,
return (strcmp(s1, s2) == 0);
}
case CONF_TYPE_OBJECT: {
int i;
for (i = e->num_desc; i > 0; i--) {
for (int i = e->num_desc; i > 0; i--) {
e++;
if (e->type != CONF_TYPE_OBJECT && !mgos_conf_value_eq(cfg, base, e)) {
return false;
Expand Down Expand Up @@ -399,9 +399,41 @@ bool mgos_conf_emit_f(const void *cfg, const void *base,
return true;
}

bool mgos_conf_copy(const struct mgos_conf_entry *schema, const void *src,
void *dst) {
bool res = true;
if (schema->type != CONF_TYPE_OBJECT) return false;
for (int i = 1; i <= schema->num_desc; i++) {
const struct mgos_conf_entry *e = schema + i;
const void *svp = (((const char *) src) + e->offset);
void *dvp = (((char *) dst) + e->offset);
switch (e->type) {
case CONF_TYPE_INT:
case CONF_TYPE_BOOL:
case CONF_TYPE_UNSIGNED_INT:
*((int *) dvp) = *((const int *) svp);
break;
case CONF_TYPE_DOUBLE:
#ifndef MGOS_BOOT_BUILD
*((double *) dvp) = *((const double *) svp);
#endif
break;
case CONF_TYPE_STRING:
*((const char **) dvp) = NULL;
if (!mgos_conf_copy_str(*((const char **) svp), (const char **) dvp)) {
res = false;
}
break;
case CONF_TYPE_OBJECT:
break;
}
}
return res;
}

void mgos_conf_free(const struct mgos_conf_entry *schema, void *cfg) {
int i;
for (i = 1; i <= schema->num_desc; i++) {
if (schema->type != CONF_TYPE_OBJECT) return;
for (int i = 1; i <= schema->num_desc; i++) {
const struct mgos_conf_entry *e = schema + i;
if (e->type == CONF_TYPE_STRING) {
const char **sp = ((const char **) (((char *) cfg) + e->offset));
Expand Down Expand Up @@ -434,7 +466,9 @@ static bool mgos_conf_str_is_default(const char *s) {
}

bool mgos_conf_copy_str(const char *s, const char **copy) {
mgos_conf_free_str(copy);
if (*copy != NULL && !mgos_conf_str_is_default(*copy)) {
free((void *) *copy);
}
if (s == NULL || mgos_conf_str_is_default(s)) {
*copy = (char *) s;
return true;
Expand All @@ -445,7 +479,7 @@ bool mgos_conf_copy_str(const char *s, const char **copy) {

void mgos_conf_free_str(const char **sp) {
if (*sp != NULL && !mgos_conf_str_is_default(*sp)) {
free((char *) *sp);
free((void *) *sp);
}
*sp = NULL;
}
Expand Down
96 changes: 96 additions & 0 deletions src/test/data/golden/mgos_config.c
Expand Up @@ -73,13 +73,37 @@ const struct mgos_config mgos_config_defaults = {
const struct mgos_config_wifi * mgos_config_get_wifi(struct mgos_config *cfg) {
return &cfg->wifi;
}
const struct mgos_conf_entry *mgos_config_schema_wifi(void) {
return mgos_conf_find_schema_entry("wifi", mgos_config_schema());
}
bool mgos_config_parse_wifi(struct mg_str json, struct mgos_config_wifi *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_wifi(const struct mgos_config_wifi *src, struct mgos_config_wifi *dst) {
return mgos_conf_copy(mgos_config_schema_wifi(), src, dst);
}
void mgos_config_free_wifi(struct mgos_config_wifi *cfg) {
return mgos_conf_free(mgos_config_schema_wifi(), cfg);
}

/* wifi.sta */
#define MGOS_CONFIG_HAVE_WIFI_STA
#define MGOS_SYS_CONFIG_HAVE_WIFI_STA
const struct mgos_config_wifi_sta * mgos_config_get_wifi_sta(struct mgos_config *cfg) {
return &cfg->wifi.sta;
}
const struct mgos_conf_entry *mgos_config_schema_wifi_sta(void) {
return mgos_conf_find_schema_entry("wifi.sta", mgos_config_schema());
}
bool mgos_config_parse_wifi_sta(struct mg_str json, struct mgos_config_wifi_sta *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_wifi_sta(const struct mgos_config_wifi_sta *src, struct mgos_config_wifi_sta *dst) {
return mgos_conf_copy(mgos_config_schema_wifi_sta(), src, dst);
}
void mgos_config_free_wifi_sta(struct mgos_config_wifi_sta *cfg) {
return mgos_conf_free(mgos_config_schema_wifi_sta(), cfg);
}

/* wifi.sta.ssid */
#define MGOS_CONFIG_HAVE_WIFI_STA_SSID
Expand Down Expand Up @@ -107,6 +131,18 @@ void mgos_config_set_wifi_sta_pass(struct mgos_config *cfg, const char * v) {
const struct mgos_config_wifi_ap * mgos_config_get_wifi_ap(struct mgos_config *cfg) {
return &cfg->wifi.ap;
}
const struct mgos_conf_entry *mgos_config_schema_wifi_ap(void) {
return mgos_conf_find_schema_entry("wifi.ap", mgos_config_schema());
}
bool mgos_config_parse_wifi_ap(struct mg_str json, struct mgos_config_wifi_ap *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_wifi_ap(const struct mgos_config_wifi_ap *src, struct mgos_config_wifi_ap *dst) {
return mgos_conf_copy(mgos_config_schema_wifi_ap(), src, dst);
}
void mgos_config_free_wifi_ap(struct mgos_config_wifi_ap *cfg) {
return mgos_conf_free(mgos_config_schema_wifi_ap(), cfg);
}

/* wifi.ap.ssid */
#define MGOS_CONFIG_HAVE_WIFI_AP_SSID
Expand Down Expand Up @@ -164,6 +200,18 @@ void mgos_config_set_foo(struct mgos_config *cfg, int v) {
const struct mgos_config_http * mgos_config_get_http(struct mgos_config *cfg) {
return &cfg->http;
}
const struct mgos_conf_entry *mgos_config_schema_http(void) {
return mgos_conf_find_schema_entry("http", mgos_config_schema());
}
bool mgos_config_parse_http(struct mg_str json, struct mgos_config_http *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_http(const struct mgos_config_http *src, struct mgos_config_http *dst) {
return mgos_conf_copy(mgos_config_schema_http(), src, dst);
}
void mgos_config_free_http(struct mgos_config_http *cfg) {
return mgos_conf_free(mgos_config_schema_http(), cfg);
}

/* http.enable */
#define MGOS_CONFIG_HAVE_HTTP_ENABLE
Expand Down Expand Up @@ -191,6 +239,18 @@ void mgos_config_set_http_port(struct mgos_config *cfg, int v) {
const struct mgos_config_debug * mgos_config_get_debug(struct mgos_config *cfg) {
return &cfg->debug;
}
const struct mgos_conf_entry *mgos_config_schema_debug(void) {
return mgos_conf_find_schema_entry("debug", mgos_config_schema());
}
bool mgos_config_parse_debug(struct mg_str json, struct mgos_config_debug *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_debug(const struct mgos_config_debug *src, struct mgos_config_debug *dst) {
return mgos_conf_copy(mgos_config_schema_debug(), src, dst);
}
void mgos_config_free_debug(struct mgos_config_debug *cfg) {
return mgos_conf_free(mgos_config_schema_debug(), cfg);
}

/* debug.level */
#define MGOS_CONFIG_HAVE_DEBUG_LEVEL
Expand Down Expand Up @@ -248,13 +308,37 @@ void mgos_config_set_debug_test_ui(struct mgos_config *cfg, unsigned int v) {
const struct mgos_config_test * mgos_config_get_test(struct mgos_config *cfg) {
return &cfg->test;
}
const struct mgos_conf_entry *mgos_config_schema_test(void) {
return mgos_conf_find_schema_entry("test", mgos_config_schema());
}
bool mgos_config_parse_test(struct mg_str json, struct mgos_config_test *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_test(const struct mgos_config_test *src, struct mgos_config_test *dst) {
return mgos_conf_copy(mgos_config_schema_test(), src, dst);
}
void mgos_config_free_test(struct mgos_config_test *cfg) {
return mgos_conf_free(mgos_config_schema_test(), cfg);
}

/* test.bar */
#define MGOS_CONFIG_HAVE_TEST_BAR
#define MGOS_SYS_CONFIG_HAVE_TEST_BAR
const struct mgos_config_test_bar * mgos_config_get_test_bar(struct mgos_config *cfg) {
return &cfg->test.bar;
}
const struct mgos_conf_entry *mgos_config_schema_test_bar(void) {
return mgos_conf_find_schema_entry("test.bar", mgos_config_schema());
}
bool mgos_config_parse_test_bar(struct mg_str json, struct mgos_config_test_bar *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_test_bar(const struct mgos_config_test_bar *src, struct mgos_config_test_bar *dst) {
return mgos_conf_copy(mgos_config_schema_test_bar(), src, dst);
}
void mgos_config_free_test_bar(struct mgos_config_test_bar *cfg) {
return mgos_conf_free(mgos_config_schema_test_bar(), cfg);
}

/* test.bar.enable */
#define MGOS_CONFIG_HAVE_TEST_BAR_ENABLE
Expand Down Expand Up @@ -282,6 +366,18 @@ void mgos_config_set_test_bar_param1(struct mgos_config *cfg, int v) {
const struct mgos_config_test_bar * mgos_config_get_test_bar1(struct mgos_config *cfg) {
return &cfg->test.bar1;
}
const struct mgos_conf_entry *mgos_config_schema_test_bar1(void) {
return mgos_conf_find_schema_entry("test.bar1", mgos_config_schema());
}
bool mgos_config_parse_test_bar1(struct mg_str json, struct mgos_config_test_bar *cfg) {
return mgos_conf_parse_sub(json, mgos_config_schema(), cfg);
}
bool mgos_config_copy_test_bar1(const struct mgos_config_test_bar *src, struct mgos_config_test_bar *dst) {
return mgos_conf_copy(mgos_config_schema_test_bar1(), src, dst);
}
void mgos_config_free_test_bar1(struct mgos_config_test_bar *cfg) {
return mgos_conf_free(mgos_config_schema_test_bar1(), cfg);
}

/* test.bar1.enable */
#define MGOS_CONFIG_HAVE_TEST_BAR1_ENABLE
Expand Down
32 changes: 32 additions & 0 deletions src/test/data/golden/mgos_config.h
Expand Up @@ -72,12 +72,20 @@ extern const struct mgos_config mgos_config_defaults;
#define MGOS_SYS_CONFIG_HAVE_WIFI
const struct mgos_config_wifi * mgos_config_get_wifi(struct mgos_config *cfg);
static inline const struct mgos_config_wifi * mgos_sys_config_get_wifi(void) { return mgos_config_get_wifi(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_wifi(void);
bool mgos_config_parse_wifi(struct mg_str json, struct mgos_config_wifi *cfg);
bool mgos_config_copy_wifi(const struct mgos_config_wifi *src, struct mgos_config_wifi *dst);
void mgos_config_free_wifi(struct mgos_config_wifi *cfg);

/* wifi.sta */
#define MGOS_CONFIG_HAVE_WIFI_STA
#define MGOS_SYS_CONFIG_HAVE_WIFI_STA
const struct mgos_config_wifi_sta * mgos_config_get_wifi_sta(struct mgos_config *cfg);
static inline const struct mgos_config_wifi_sta * mgos_sys_config_get_wifi_sta(void) { return mgos_config_get_wifi_sta(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_wifi_sta(void);
bool mgos_config_parse_wifi_sta(struct mg_str json, struct mgos_config_wifi_sta *cfg);
bool mgos_config_copy_wifi_sta(const struct mgos_config_wifi_sta *src, struct mgos_config_wifi_sta *dst);
void mgos_config_free_wifi_sta(struct mgos_config_wifi_sta *cfg);

/* wifi.sta.ssid */
#define MGOS_CONFIG_HAVE_WIFI_STA_SSID
Expand All @@ -100,6 +108,10 @@ static inline void mgos_sys_config_set_wifi_sta_pass(const char * v) { mgos_conf
#define MGOS_SYS_CONFIG_HAVE_WIFI_AP
const struct mgos_config_wifi_ap * mgos_config_get_wifi_ap(struct mgos_config *cfg);
static inline const struct mgos_config_wifi_ap * mgos_sys_config_get_wifi_ap(void) { return mgos_config_get_wifi_ap(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_wifi_ap(void);
bool mgos_config_parse_wifi_ap(struct mg_str json, struct mgos_config_wifi_ap *cfg);
bool mgos_config_copy_wifi_ap(const struct mgos_config_wifi_ap *src, struct mgos_config_wifi_ap *dst);
void mgos_config_free_wifi_ap(struct mgos_config_wifi_ap *cfg);

/* wifi.ap.ssid */
#define MGOS_CONFIG_HAVE_WIFI_AP_SSID
Expand Down Expand Up @@ -146,6 +158,10 @@ static inline void mgos_sys_config_set_foo(int v) { mgos_config_set_foo(&mgos_sy
#define MGOS_SYS_CONFIG_HAVE_HTTP
const struct mgos_config_http * mgos_config_get_http(struct mgos_config *cfg);
static inline const struct mgos_config_http * mgos_sys_config_get_http(void) { return mgos_config_get_http(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_http(void);
bool mgos_config_parse_http(struct mg_str json, struct mgos_config_http *cfg);
bool mgos_config_copy_http(const struct mgos_config_http *src, struct mgos_config_http *dst);
void mgos_config_free_http(struct mgos_config_http *cfg);

/* http.enable */
#define MGOS_CONFIG_HAVE_HTTP_ENABLE
Expand All @@ -168,6 +184,10 @@ static inline void mgos_sys_config_set_http_port(int v) { mgos_config_set_http_p
#define MGOS_SYS_CONFIG_HAVE_DEBUG
const struct mgos_config_debug * mgos_config_get_debug(struct mgos_config *cfg);
static inline const struct mgos_config_debug * mgos_sys_config_get_debug(void) { return mgos_config_get_debug(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_debug(void);
bool mgos_config_parse_debug(struct mg_str json, struct mgos_config_debug *cfg);
bool mgos_config_copy_debug(const struct mgos_config_debug *src, struct mgos_config_debug *dst);
void mgos_config_free_debug(struct mgos_config_debug *cfg);

/* debug.level */
#define MGOS_CONFIG_HAVE_DEBUG_LEVEL
Expand Down Expand Up @@ -214,12 +234,20 @@ static inline void mgos_sys_config_set_debug_test_ui(unsigned int v) { mgos_conf
#define MGOS_SYS_CONFIG_HAVE_TEST
const struct mgos_config_test * mgos_config_get_test(struct mgos_config *cfg);
static inline const struct mgos_config_test * mgos_sys_config_get_test(void) { return mgos_config_get_test(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_test(void);
bool mgos_config_parse_test(struct mg_str json, struct mgos_config_test *cfg);
bool mgos_config_copy_test(const struct mgos_config_test *src, struct mgos_config_test *dst);
void mgos_config_free_test(struct mgos_config_test *cfg);

/* test.bar */
#define MGOS_CONFIG_HAVE_TEST_BAR
#define MGOS_SYS_CONFIG_HAVE_TEST_BAR
const struct mgos_config_test_bar * mgos_config_get_test_bar(struct mgos_config *cfg);
static inline const struct mgos_config_test_bar * mgos_sys_config_get_test_bar(void) { return mgos_config_get_test_bar(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_test_bar(void);
bool mgos_config_parse_test_bar(struct mg_str json, struct mgos_config_test_bar *cfg);
bool mgos_config_copy_test_bar(const struct mgos_config_test_bar *src, struct mgos_config_test_bar *dst);
void mgos_config_free_test_bar(struct mgos_config_test_bar *cfg);

/* test.bar.enable */
#define MGOS_CONFIG_HAVE_TEST_BAR_ENABLE
Expand All @@ -242,6 +270,10 @@ static inline void mgos_sys_config_set_test_bar_param1(int v) { mgos_config_set_
#define MGOS_SYS_CONFIG_HAVE_TEST_BAR1
const struct mgos_config_test_bar * mgos_config_get_test_bar1(struct mgos_config *cfg);
static inline const struct mgos_config_test_bar * mgos_sys_config_get_test_bar1(void) { return mgos_config_get_test_bar1(&mgos_sys_config); }
const struct mgos_conf_entry *mgos_config_schema_test_bar1(void);
bool mgos_config_parse_test_bar1(struct mg_str json, struct mgos_config_test_bar *cfg);
bool mgos_config_copy_test_bar1(const struct mgos_config_test_bar *src, struct mgos_config_test_bar *dst);
void mgos_config_free_test_bar1(struct mgos_config_test_bar *cfg);

/* test.bar1.enable */
#define MGOS_CONFIG_HAVE_TEST_BAR1_ENABLE
Expand Down
12 changes: 12 additions & 0 deletions src/test/unit_test.c
Expand Up @@ -21,6 +21,7 @@ static const char *test_config(void) {
char *json2 = cs_read_file("data/overrides.json", &size);
const struct mgos_conf_entry *schema = mgos_config_schema();
struct mgos_config conf;
struct mgos_config_wifi conf_wifi2;

ASSERT(json2 != NULL);
cs_log_set_level(LL_NONE);
Expand Down Expand Up @@ -53,6 +54,17 @@ static const char *test_config(void) {
mgos_sys_config_set_wifi_ap_channel(123);
ASSERT_EQ(mgos_sys_config_get_wifi_ap_channel(), 123);

/* Test copying */
mgos_config_copy_wifi(&conf.wifi, &conf_wifi2);
ASSERT_PTREQ(conf.wifi.ap.ssid,
conf_wifi2.ap.ssid); // Shared const pointers.
ASSERT_PTRNE(conf.wifi.sta.pass,
conf_wifi2.sta.pass); // Duplicated heap values.
ASSERT_STREQ(conf.wifi.sta.pass, conf_wifi2.sta.pass);
ASSERT_EQ(conf.wifi.ap.channel, conf_wifi2.ap.channel);

mgos_config_free_wifi(&conf_wifi2);

mgos_conf_free(schema, &conf);

free(json2);
Expand Down

0 comments on commit f39a7df

Please sign in to comment.