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);