You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/01/05 19:58:07 UTC
incubator-mynewt-larva git commit: Start of config system.
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master a54bfb3f9 -> fe6e81e15
Start of config system.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/fe6e81e1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/fe6e81e1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/fe6e81e1
Branch: refs/heads/master
Commit: fe6e81e15dde17c8992f2f2949814cdb8fb01cd8
Parents: a54bfb3
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Jan 5 10:57:42 2016 -0800
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Jan 5 10:57:42 2016 -0800
----------------------------------------------------------------------
libs/util/include/util/config.h | 71 ++++++++++
libs/util/src/config.c | 113 +++++++++++++++
libs/util/src/config_cli.c | 160 +++++++++++++++++++++
libs/util/src/test/conf_test.c | 229 +++++++++++++++++++++++++++++++
libs/util/src/test/util_test.c | 1 +
libs/util/src/test/util_test_priv.h | 1 +
project/blinky/src/main.c | 3 +
7 files changed, 578 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/libs/util/include/util/config.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/config.h b/libs/util/include/util/config.h
new file mode 100644
index 0000000..a90e5c9
--- /dev/null
+++ b/libs/util/include/util/config.h
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 __UTIL_CONFIG_H_
+#define __UTIL_CONFIG_H_
+
+#include <os/queue.h>
+#include <stdint.h>
+
+#define CONF_MAX_DIR_DEPTH 8 /* max depth of config tree */
+#define CONF_NAME_SEPARATOR "/"
+
+enum conf_type {
+ CONF_NONE = 0,
+ CONF_DIR,
+ CONF_INT8,
+ CONF_INT16,
+ CONF_INT32,
+ CONF_INT64,
+ CONF_STRING,
+ CONF_BYTES,
+ CONF_FLOAT,
+ CONF_DOUBLE
+} __attribute__((__packed__));
+
+struct conf_entry {
+ const char *c_name;
+ enum conf_type c_type;
+ union {
+ struct { /* INT8, INT16, INT32, INT64, FLOAT, DOUBLE */
+ void *val;
+ } single;
+ struct { /* STRING, BYTES */
+ uint16_t maxlen;
+ uint16_t len;
+ void *val;
+ } array;
+ } c_val;
+};
+
+struct conf_entry_dir {
+ const char *c_name;
+ enum conf_type c_type; /* DIR */
+};
+
+struct conf_node {
+ SLIST_ENTRY(conf_node) cn_next;
+ SLIST_HEAD(, conf_node) cn_children;
+ struct conf_entry *cn_array;
+ int cn_cnt;
+};
+
+int conf_module_init(void);
+int conf_register(struct conf_node *parent, struct conf_node *child);
+struct conf_entry *conf_lookup(int argc, char **argv);
+
+int conf_parse_name(char *name, int *name_argc, char *name_argv[]);
+
+#endif /* __UTIL_CONFIG_H_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/libs/util/src/config.c
----------------------------------------------------------------------
diff --git a/libs/util/src/config.c b/libs/util/src/config.c
new file mode 100644
index 0000000..ccc4d69
--- /dev/null
+++ b/libs/util/src/config.c
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <string.h>
+
+#include "util/config.h"
+
+#ifdef SHELL_PRESENT
+#include <shell/shell.h>
+#include <console/console.h>
+#endif
+
+static struct conf_node g_conf_root;
+
+static struct conf_entry *
+conf_node_match(struct conf_node *cn, const char *name)
+{
+ int i;
+
+ for (i = 0; i < cn->cn_cnt; i++) {
+ if (!strcmp(name, cn->cn_array[i].c_name)) {
+ return &cn->cn_array[i];
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Register config node to a specific spot in the tree.
+ */
+int
+conf_register(struct conf_node *parent, struct conf_node *child)
+{
+ struct conf_node *cn;
+ int i;
+
+ if (!parent) {
+ parent = &g_conf_root;
+ }
+
+ for (i = 0; i < child->cn_cnt; i++) {
+ SLIST_FOREACH(cn, &parent->cn_children, cn_next) {
+ if (conf_node_match(cn, child->cn_array[i].c_name)) {
+ return -1;
+ }
+ }
+ }
+ SLIST_INSERT_HEAD(&parent->cn_children, child, cn_next);
+ return 0;
+}
+
+/*
+ * Lookup conf_entry based on name.
+ */
+struct conf_entry *
+conf_lookup(int argc, char **argv)
+{
+ int i;
+ struct conf_node *parent = &g_conf_root;
+ struct conf_entry *ret = NULL;
+ struct conf_node *cn;
+
+ for (i = 0; i < argc; i++) {
+ ret = NULL;
+ SLIST_FOREACH(cn, &parent->cn_children, cn_next) {
+ ret = conf_node_match(cn, argv[i]);
+ if (ret) {
+ break;
+ }
+ }
+ parent = cn;
+ if (!parent) {
+ return NULL;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Separate string into argv array.
+ */
+int
+conf_parse_name(char *name, int *name_argc, char *name_argv[])
+{
+ char *tok;
+ char *tok_ptr;
+ int i;
+
+ tok_ptr = NULL;
+ tok = strtok_r(name, CONF_NAME_SEPARATOR, &tok_ptr);
+
+ i = 0;
+ while (tok) {
+ name_argv[i++] = tok;
+ tok = strtok_r(NULL, CONF_NAME_SEPARATOR, &tok_ptr);
+ }
+ *name_argc = i;
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/libs/util/src/config_cli.c
----------------------------------------------------------------------
diff --git a/libs/util/src/config_cli.c b/libs/util/src/config_cli.c
new file mode 100644
index 0000000..2cc6a96
--- /dev/null
+++ b/libs/util/src/config_cli.c
@@ -0,0 +1,160 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <stddef.h>
+
+#include "util/config.h"
+
+#ifdef SHELL_PRESENT
+#include <string.h>
+
+#include <shell/shell.h>
+#include <console/console.h>
+
+static struct shell_cmd shell_conf_cmd;
+
+static void
+shell_conf_display(struct conf_entry *ce)
+{
+ int32_t val;
+
+ if (ce->c_type == CONF_STRING) {
+ console_printf("%s\n", (char *)ce->c_val.array.val);
+ return;
+ }
+ switch (ce->c_type) {
+ case CONF_INT8:
+ case CONF_INT16:
+ case CONF_INT32:
+ if (ce->c_type == CONF_INT8) {
+ val = *(int8_t *)ce->c_val.single.val;
+ } else if (ce->c_type == CONF_INT16) {
+ val = *(int16_t *)ce->c_val.single.val;
+ } else {
+ val = *(int32_t *)ce->c_val.single.val;
+ }
+ console_printf("%ld (0x%lx)\n", (long)val, (long)val);
+ break;
+ default:
+ console_printf("Can't print type %d\n", ce->c_type);
+ return;
+ }
+}
+
+static int
+shell_conf_set(struct conf_entry *ce, char *val_str)
+{
+ int32_t val;
+ char *eptr;
+
+ switch (ce->c_type) {
+ case CONF_INT8:
+ case CONF_INT16:
+ case CONF_INT32:
+ val = strtol(val_str, &eptr, 0);
+ if (*eptr != '\0') {
+ goto err;
+ }
+ if (ce->c_type == CONF_INT8) {
+ if (val < INT8_MIN || val > UINT8_MAX) {
+ goto err;
+ }
+ *(int8_t *)ce->c_val.single.val = val;
+ } else if (ce->c_type == CONF_INT16) {
+ if (val < INT16_MIN || val > UINT16_MAX) {
+ goto err;
+ }
+ *(int16_t *)ce->c_val.single.val = val;
+ } else if (ce->c_type == CONF_INT32) {
+ *(int32_t *)ce->c_val.single.val = val;
+ }
+ break;
+ case CONF_STRING:
+ val = strlen(val_str);
+ if (val + 1 > ce->c_val.array.maxlen) {
+ goto err;
+ }
+ strcpy(ce->c_val.array.val, val_str);
+ ce->c_val.array.len = val;
+ break;
+ default:
+ console_printf("Can't parse type %d\n", ce->c_type);
+ break;
+ }
+ return 0;
+err:
+ return -1;
+}
+
+static int
+shell_conf_command(int argc, char **argv)
+{
+ char *name = NULL;
+ char *val = NULL;
+ char *name_argv[CONF_MAX_DIR_DEPTH];
+ int name_argc;
+ int rc;
+ struct conf_entry *ce;
+
+ switch (argc) {
+ case 1:
+ break;
+ case 2:
+ name = argv[1];
+ break;
+ case 3:
+ name = argv[1];
+ val = argv[2];
+ break;
+ default:
+ goto err;
+ }
+
+ rc = conf_parse_name(name, &name_argc, name_argv);
+ if (rc) {
+ goto err;
+ }
+
+ ce = conf_lookup(name_argc, name_argv);
+ if (!ce) {
+ console_printf("No such config variable\n");
+ goto err;
+ }
+
+ if (!val) {
+ shell_conf_display(ce);
+ } else {
+ rc = shell_conf_set(ce, val);
+ if (rc) {
+ console_printf("Failed to set\n");
+ goto err;
+ }
+ }
+ return 0;
+err:
+ console_printf("Invalid args\n");
+ return 0;
+}
+#endif
+
+int conf_module_init(void)
+{
+#ifdef SHELL_PRESENT
+ shell_cmd_register(&shell_conf_cmd, "config", shell_conf_command);
+#endif
+ return 0;
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/libs/util/src/test/conf_test.c
----------------------------------------------------------------------
diff --git a/libs/util/src/test/conf_test.c b/libs/util/src/test/conf_test.c
new file mode 100644
index 0000000..8aa3712
--- /dev/null
+++ b/libs/util/src/test/conf_test.c
@@ -0,0 +1,229 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <stdio.h>
+#include <string.h>
+
+#include "os/os.h"
+#include "testutil/testutil.h"
+#include "util/config.h"
+
+uint8_t val8;
+
+static struct conf_entry ce1 = {
+ .c_name = "ce1",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+};
+
+static struct conf_node cn1 = {
+ .cn_cnt = 1,
+ .cn_array = &ce1
+};
+
+static struct conf_entry ce2 = {
+ .c_name = "ce2",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+};
+
+static struct conf_node cn2 = {
+ .cn_cnt = 1,
+ .cn_array = &ce2
+};
+
+static struct conf_entry ce_arr1[2] = {
+ [0] = {
+ .c_name = "cea1",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+ },
+ [1] = {
+ .c_name = "cea2",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+ }
+};
+
+static struct conf_node cn_arr1 = {
+ .cn_cnt = 2,
+ .cn_array = ce_arr1
+};
+
+static struct conf_entry ce_arr2[2] = {
+ [0] = {
+ .c_name = "ce21",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+ },
+ [1] = {
+ .c_name = "cea2",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+ }
+};
+
+static struct conf_node cn_arr2 = {
+ .cn_cnt = 2,
+ .cn_array = ce_arr2
+};
+
+static struct conf_entry_dir ce_dir = {
+ .c_name = "foo",
+ .c_type = CONF_DIR
+};
+
+static struct conf_node cn_dir = {
+ .cn_cnt = 1,
+ .cn_array = (struct conf_entry *)&ce_dir
+};
+
+static struct conf_entry ce_foo_arr1[2] = {
+ [0] = {
+ .c_name = "foo1",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+ },
+ [1] = {
+ .c_name = "foo2",
+ .c_type = CONF_INT8,
+ .c_val.single.val = &val8
+ }
+};
+
+static struct conf_node cn_foo_arr1 = {
+ .cn_cnt = 2,
+ .cn_array = ce_foo_arr1
+};
+
+TEST_CASE(config_empty_lookups)
+{
+ struct conf_entry *ce;
+ char *names1[] = { "foo", "bar" };
+
+ ce = conf_lookup(0, NULL);
+ TEST_ASSERT(ce == NULL);
+
+ ce = conf_lookup(1, names1);
+ TEST_ASSERT(ce == NULL);
+
+ ce = conf_lookup(2, names1);
+ TEST_ASSERT(ce == NULL);
+}
+
+TEST_CASE(config_test_insert)
+{
+ int rc;
+
+ /*
+ * Add 2 new ones
+ */
+ rc = conf_register(NULL, &cn1);
+ TEST_ASSERT(rc == 0);
+ rc = conf_register(NULL, &cn2);
+ TEST_ASSERT(rc == 0);
+
+ /*
+ * Fail adding same ones again
+ */
+ rc = conf_register(NULL, &cn1);
+ TEST_ASSERT(rc != 0);
+ rc = conf_register(NULL, &cn2);
+ TEST_ASSERT(rc != 0);
+
+ /*
+ * Add with multiple conf_entries
+ */
+ rc = conf_register(NULL, &cn_arr1);
+ TEST_ASSERT(rc == 0);
+
+ /*
+ * Cannot add it again
+ */
+ rc = conf_register(NULL, &cn_arr1);
+ TEST_ASSERT(rc != 0);
+
+ /*
+ * Should fail right away
+ */
+ rc = conf_register(NULL, &cn_arr2);
+ TEST_ASSERT(rc != 0);
+
+}
+
+TEST_CASE(config_test_lookup)
+{
+ struct conf_entry *ce;
+ char *names1[] = { "foo", "bar" };
+ char *names2[] = { "ce1" };
+ char *names3[] = { "cea2" };
+
+ ce = conf_lookup(0, NULL);
+ TEST_ASSERT(ce == NULL);
+
+ ce = conf_lookup(1, names1);
+ TEST_ASSERT(ce == NULL);
+
+ ce = conf_lookup(2, names1);
+ TEST_ASSERT(ce == NULL);
+
+ ce = conf_lookup(1, names2);
+ TEST_ASSERT(ce != NULL);
+ TEST_ASSERT(!strcmp(ce->c_name, names2[0]));
+
+ ce = conf_lookup(1, names3);
+ TEST_ASSERT(ce != NULL);
+ TEST_ASSERT(!strcmp(ce->c_name, names3[0]));
+}
+
+TEST_CASE(config_test_dir)
+{
+ int rc;
+ struct conf_entry *ce;
+ char *names1[] = { "foo", "foo1" };
+ char *names2[] = { "foo", "foo2" };
+ char *names3[] = { "foo", "foo3" };
+
+ /*
+ * Add directory node, and node under.
+ */
+ rc = conf_register(NULL, &cn_dir);
+ TEST_ASSERT(rc == 0);
+ rc = conf_register(&cn_dir, &cn_foo_arr1);
+ TEST_ASSERT(rc == 0);
+
+ ce = conf_lookup(1, names1);
+ TEST_ASSERT(ce != NULL);
+ TEST_ASSERT(ce->c_type == CONF_DIR);
+
+ ce = conf_lookup(2, names1);
+ TEST_ASSERT(ce != NULL);
+ TEST_ASSERT(!strcmp(ce->c_name, names1[1]));
+
+ ce = conf_lookup(2, names2);
+ TEST_ASSERT(ce != NULL);
+ TEST_ASSERT(!strcmp(ce->c_name, names2[1]));
+
+ ce = conf_lookup(2, names3);
+ TEST_ASSERT(ce == NULL);
+}
+
+TEST_SUITE(config_test_suite)
+{
+ config_empty_lookups();
+ config_test_insert();
+ config_test_lookup();
+ config_test_dir();
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/libs/util/src/test/util_test.c
----------------------------------------------------------------------
diff --git a/libs/util/src/test/util_test.c b/libs/util/src/test/util_test.c
index 9998fa7..bbedf9d 100644
--- a/libs/util/src/test/util_test.c
+++ b/libs/util/src/test/util_test.c
@@ -24,6 +24,7 @@ util_test_all(void)
{
cbmem_test_suite();
flash_map_test_suite();
+ config_test_suite();
return tu_case_failed;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/libs/util/src/test/util_test_priv.h
----------------------------------------------------------------------
diff --git a/libs/util/src/test/util_test_priv.h b/libs/util/src/test/util_test_priv.h
index d6f8da4..5132bbe 100644
--- a/libs/util/src/test/util_test_priv.h
+++ b/libs/util/src/test/util_test_priv.h
@@ -19,5 +19,6 @@
int cbmem_test_suite(void);
int flash_map_test_suite(void);
+int config_test_suite(void);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/fe6e81e1/project/blinky/src/main.c
----------------------------------------------------------------------
diff --git a/project/blinky/src/main.c b/project/blinky/src/main.c
index 223c1fd..0e3c289 100755
--- a/project/blinky/src/main.c
+++ b/project/blinky/src/main.c
@@ -20,6 +20,7 @@
#include "shell/shell.h"
#include "util/log.h"
#include "util/stats.h"
+#include "util/config.h"
#include <assert.h>
#include <string.h>
#ifdef ARCH_sim
@@ -157,6 +158,8 @@ main(int argc, char **argv)
mcu_sim_parse_args(argc, argv);
#endif
+ conf_module_init();
+
cbmem_init(&log_mem, log_buf, sizeof(log_buf));
util_log_cbmem_handler_init(&log_mem_handler, &log_mem);
util_log_register("log", &my_log, &log_mem_handler);