-
Notifications
You must be signed in to change notification settings - Fork 362
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
util/scfg: Simple config lib on top of sys/config
- Loading branch information
1 parent
170053f
commit b8db31a
Showing
3 changed files
with
378 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
#ifndef H_SCFG_ | ||
#define H_SCFG_ | ||
|
||
#include "config/config.h" | ||
|
||
struct scfg_setting { | ||
/** The name of the setting. */ | ||
const char *name; | ||
|
||
/** Points to the RAM replica of the setting value. */ | ||
void *val; | ||
|
||
/** | ||
* Only needed for string settings. Indicates the maximum length this | ||
* setting's value can by. | ||
*/ | ||
int max_len; | ||
|
||
/** This setting's data data. One of the CONF_[...] constants. */ | ||
uint8_t type; | ||
|
||
/** | ||
* Whether this setting contains private data. If 1, the value is hidden | ||
* in config dump output. | ||
*/ | ||
uint8_t f_private : 1; | ||
}; | ||
|
||
struct scfg_group { | ||
/*** Public */ | ||
/** This array must be terminated with an `{ 0 }` entry. */ | ||
const struct scfg_setting *settings; | ||
|
||
/*** Private */ | ||
struct conf_handler handler; | ||
}; | ||
|
||
/** | ||
* Persists a single setting. | ||
* | ||
* @param group The group that the setting belongs to. | ||
* @param setting The setting to save. | ||
* | ||
* @return 0 on success; SYS_E[...] code on failure. | ||
*/ | ||
int scfg_save_setting(const struct scfg_group *group, | ||
const struct scfg_setting *setting); | ||
|
||
/** | ||
* Persists the setting with the specified name. | ||
* | ||
* @param group The group that the setting belongs to. | ||
* @param setting_name The name of the setting to save. | ||
* | ||
* @return 0 on success; SYS_E[...] code on failure. | ||
*/ | ||
int scfg_save_name(const struct scfg_group *group, const char *setting_name); | ||
|
||
/** | ||
* Persists the setting whose value is stored in the specified variable. The | ||
* specified value address should be the same one that was specified in the | ||
* `scfg_setting` definition. | ||
* | ||
* @param group The group that the setting belongs to. | ||
* @param val The address of the setting's value variable. | ||
* | ||
* @return 0 on success; SYS_E[...] code on failure. | ||
*/ | ||
int scfg_save_val(const struct scfg_group *group, const void *val); | ||
|
||
/** | ||
* Registers a group of configuration settings. The group's public members | ||
* must be populated before this function is called. | ||
* | ||
* @param group The group to register | ||
* @param name The name of the settings group. | ||
* | ||
* @return 0 on success; SYS_E[...] code on failure. | ||
*/ | ||
int scfg_register(struct scfg_group *group, char *name); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you under the Apache License, Version 2.0 (the | ||
# "License"); you may not use this file except in compliance | ||
# with the License. You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an | ||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
# KIND, either express or implied. See the License for the | ||
# specific language governing permissions and limitations | ||
# under the License. | ||
# | ||
|
||
pkg.name: util/scfg | ||
pkg.description: XXX | ||
pkg.deps: | ||
- "@apache-mynewt-core/sys/config" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
#include "os/mynewt.h" | ||
#include "scfg/scfg.h" | ||
|
||
#define SCFG_MAX_SETTING_ID_LEN 64 | ||
#define SCFG_MAX_NUM_STR_LEN (sizeof "18446744073709551615") | ||
|
||
#define SCFG_FOREACH_SETTING(group, s) \ | ||
for (s = (group)->settings; s->name != NULL; s++) | ||
|
||
static void | ||
scfg_setting_id(const char *group_name, const char *setting_name, char *buf) | ||
{ | ||
int setting_len; | ||
int group_len; | ||
int off; | ||
|
||
group_len = strlen(group_name); | ||
setting_len = strlen(setting_name); | ||
|
||
/* <group>/<setting> */ | ||
assert(group_len + 1 + setting_len <= SCFG_MAX_SETTING_ID_LEN); | ||
|
||
off = 0; | ||
|
||
memcpy(&buf[off], group_name, group_len); | ||
off += group_len; | ||
|
||
buf[off] = '/'; | ||
off++; | ||
|
||
memcpy(&buf[off], setting_name, setting_len); | ||
off += setting_len; | ||
|
||
buf[off] = '\0'; | ||
off++; | ||
} | ||
|
||
static struct scfg_setting * | ||
scfg_find_setting_by_name(const struct scfg_group *group, | ||
const char *setting_name) | ||
{ | ||
const struct scfg_setting *setting; | ||
|
||
SCFG_FOREACH_SETTING(group, setting) { | ||
if (strcmp(setting->name, setting_name) == 0) { | ||
return (struct scfg_setting *)setting; | ||
} | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
static struct scfg_setting * | ||
scfg_find_setting_by_val(const struct scfg_group *group, const void *val) | ||
{ | ||
const struct scfg_setting *setting; | ||
|
||
SCFG_FOREACH_SETTING(group, setting) { | ||
if (setting->val == val) { | ||
return (struct scfg_setting *)setting; | ||
} | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
/** | ||
* Conf get handler. Converts a setting's underlying variable to a string. | ||
*/ | ||
static char * | ||
scfg_handler_get(int argc, char **argv, char *buf, int max_len, void *arg) | ||
{ | ||
const struct scfg_setting *setting; | ||
struct scfg_group *group; | ||
|
||
group = arg; | ||
|
||
if (argc < 1) { | ||
return NULL; | ||
} | ||
|
||
setting = scfg_find_setting_by_name(group, argv[0]); | ||
if (setting == NULL) { | ||
return NULL; | ||
} | ||
|
||
return conf_str_from_value(setting->type, setting->val, buf, max_len); | ||
} | ||
|
||
/** | ||
* Conf set handler. Converts from a string-representation and writes the | ||
* result to the setting's underlying variable. | ||
*/ | ||
static int | ||
scfg_handler_set(int argc, char **argv, char *val, void *arg) | ||
{ | ||
const struct scfg_setting *setting; | ||
struct scfg_group *group; | ||
int rc; | ||
|
||
group = arg; | ||
|
||
if (argc < 1) { | ||
return SYS_EINVAL; | ||
} | ||
|
||
setting = scfg_find_setting_by_name(group, argv[0]); | ||
if (setting == NULL) { | ||
return SYS_ENOENT; | ||
} | ||
|
||
rc = conf_value_from_str(val, setting->type, setting->val, | ||
setting->max_len); | ||
if (rc != 0) { | ||
return os_error_to_sys(rc); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int | ||
scfg_handler_export(void (*func)(char *name, char *val), | ||
enum conf_export_tgt tgt, void *arg) | ||
{ | ||
const struct scfg_setting *setting; | ||
struct scfg_group *group; | ||
char val_buf[SCFG_MAX_NUM_STR_LEN]; | ||
char id_buf[SCFG_MAX_SETTING_ID_LEN]; | ||
char *val; | ||
|
||
group = arg; | ||
|
||
SCFG_FOREACH_SETTING(group, setting) { | ||
scfg_setting_id(group->handler.ch_name, setting->name, id_buf); | ||
if (setting->f_private) { | ||
val = "<set>"; | ||
} else { | ||
val = conf_str_from_value(setting->type, setting->val, | ||
val_buf, sizeof val_buf); | ||
} | ||
func(id_buf, val); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int | ||
scfg_save_setting(const struct scfg_group *group, | ||
const struct scfg_setting *setting) | ||
{ | ||
char id_buf[SCFG_MAX_SETTING_ID_LEN]; | ||
char val_buf[SCFG_MAX_NUM_STR_LEN]; | ||
char *val; | ||
int rc; | ||
|
||
val = conf_str_from_value(setting->type, setting->val, | ||
val_buf, sizeof val_buf); | ||
if (val == NULL) { | ||
return SYS_EUNKNOWN; | ||
} | ||
|
||
scfg_setting_id(group->handler.ch_name, setting->name, id_buf); | ||
|
||
rc = conf_save_one(id_buf, val); | ||
if (rc != 0) { | ||
return os_error_to_sys(rc); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int | ||
scfg_save_name(const struct scfg_group *group, const char *setting_name) | ||
{ | ||
const struct scfg_setting *setting; | ||
|
||
setting = scfg_find_setting_by_name(group, setting_name); | ||
if (setting == NULL) { | ||
return SYS_ENOENT; | ||
} | ||
|
||
return scfg_save_setting(group, setting); | ||
} | ||
|
||
int | ||
scfg_save_val(const struct scfg_group *group, const void *val) | ||
{ | ||
const struct scfg_setting *setting; | ||
|
||
setting = scfg_find_setting_by_val(group, val); | ||
if (setting == NULL) { | ||
return SYS_ENOENT; | ||
} | ||
|
||
return scfg_save_setting(group, setting); | ||
} | ||
|
||
int | ||
scfg_register(struct scfg_group *group, char *name) | ||
{ | ||
const struct scfg_setting *setting; | ||
int rc; | ||
|
||
SCFG_FOREACH_SETTING(group, setting) { | ||
switch (setting->type) { | ||
case CONF_INT8: | ||
case CONF_INT16: | ||
case CONF_INT32: | ||
case CONF_INT64: | ||
case CONF_STRING: | ||
case CONF_BOOL: | ||
break; | ||
|
||
default: | ||
/* We don't know how to (de)serialize the other data types. */ | ||
return SYS_EINVAL; | ||
} | ||
} | ||
|
||
group->handler = (struct conf_handler) { | ||
.ch_name = name, | ||
.ch_get_ext = scfg_handler_get, | ||
.ch_set_ext = scfg_handler_set, | ||
.ch_export_ext = scfg_handler_export, | ||
.ch_arg = group, | ||
.ch_ext = true, | ||
}; | ||
|
||
rc = conf_register(&group->handler); | ||
if (rc != 0) { | ||
return os_error_to_sys(rc); | ||
} | ||
|
||
return 0; | ||
} |