add node helpers
authorOlivier Matz <zer0@droids-corp.org>
Thu, 2 Aug 2018 20:03:04 +0000 (22:03 +0200)
committerOlivier Matz <zer0@droids-corp.org>
Thu, 2 Aug 2018 20:03:04 +0000 (22:03 +0200)
lib/Makefile
lib/ecoli_node_helper.c [new file with mode: 0644]
lib/ecoli_node_helper.h [new file with mode: 0644]

index 0d5f1e1..6808c97 100644 (file)
@@ -37,6 +37,7 @@ srcs += ecoli_node_expr.c
 srcs += ecoli_node_expr_test.c
 srcs += ecoli_node_dynamic.c
 srcs += ecoli_node_file.c
+srcs += ecoli_node_helper.c
 srcs += ecoli_node_int.c
 srcs += ecoli_node_many.c
 srcs += ecoli_node_none.c
diff --git a/lib/ecoli_node_helper.c b/lib/ecoli_node_helper.c
new file mode 100644 (file)
index 0000000..b2be8f7
--- /dev/null
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2018, Olivier MATZ <zer0@droids-corp.org>
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <errno.h>
+
+#include <ecoli_malloc.h>
+#include <ecoli_config.h>
+#include <ecoli_node.h>
+#include <ecoli_node_helper.h>
+
+struct ec_node **
+ec_node_config_node_list_to_table(const struct ec_config *config,
+                               size_t *len)
+{
+       struct ec_node **table = NULL;
+       struct ec_config *child;
+       size_t n, i;
+
+       *len = 0;
+
+       if (config == NULL) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       if (ec_config_get_type(config) != EC_CONFIG_TYPE_LIST) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       n = 0;
+       TAILQ_FOREACH(child, &config->list, next) {
+               if (ec_config_get_type(child) != EC_CONFIG_TYPE_NODE) {
+                       errno = EINVAL;
+                       return NULL;
+               }
+               n++;
+       }
+
+       table = ec_malloc(n * sizeof(*table));
+       if (table == NULL)
+               goto fail;
+
+       n = 0;
+       TAILQ_FOREACH(child, &config->list, next) {
+               table[n] = ec_node_clone(child->node);
+               n++;
+       }
+
+       *len = n;
+
+       return table;
+
+fail:
+       if (table != NULL) {
+               for (i = 0; i < n; i++)
+                       ec_node_free(table[i]);
+       }
+       ec_free(table);
+
+       return NULL;
+}
+
+struct ec_config *
+ec_node_config_node_list_from_vargs(va_list ap)
+{
+       struct ec_config *list = NULL;
+       struct ec_node *node;
+
+       list = ec_config_list();
+       if (list == NULL)
+               goto fail;
+
+       for (; node != EC_NODE_ENDLIST; node = va_arg(ap, struct ec_node *)) {
+               if (node == NULL)
+                       goto fail;
+
+               if (ec_config_list_add(list, ec_config_node(node)) < 0)
+                       goto fail;
+       }
+
+       return list;
+
+fail:
+       for (; node != EC_NODE_ENDLIST; node = va_arg(ap, struct ec_node *))
+               ec_node_free(node);
+       ec_config_free(list);
+
+       return NULL;
+}
diff --git a/lib/ecoli_node_helper.h b/lib/ecoli_node_helper.h
new file mode 100644 (file)
index 0000000..9dbf519
--- /dev/null
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2018, Olivier MATZ <zer0@droids-corp.org>
+ */
+
+/**
+ * Helpers that are commonly used in nodes.
+ */
+
+#ifndef ECOLI_NODE_HELPERS_
+#define ECOLI_NODE_HELPERS
+
+struct ec_node;
+
+/**
+ * Build a node table from a node list in a ec_config.
+ *
+ * The function takes a node configuration as parameter, which must be a
+ * node list. From it, a node table is built. A reference is taken for
+ * each node.
+ *
+ * On error, no reference is taken.
+ *
+ * @param config
+ *   The configuration (type must be a list of nodes). If it is
+ *   NULL, an error is returned.
+ * @param len
+ *   The length of the allocated table on success, or 0 on error.
+ * @return
+ *   The allocated node table, that must be freed by the caller:
+ *   each entry must be freed with ec_node_free() and the table
+ *   with ec_free(). On error, NULL is returned and errno is set.
+ */
+struct ec_node **
+ec_node_config_node_list_to_table(const struct ec_config *config,
+                               size_t *len);
+
+/**
+ * Build a list of config nodes from variable arguments.
+ *
+ * The va_list argument is a list of pointer to ec_node structures,
+ * terminated with EC_NODE_ENDLIST.
+ *
+ * This helper is used by nodes that contain a list of nodes,
+ * like "seq", "or", ...
+ *
+ * @param ap
+ *   List of pointer to ec_node structures, terminated with
+ *   EC_NODE_ENDLIST.
+ * @return
+ *   A pointer to an ec_config structure. In this case, the
+ *   nodes will be freed when the config structure will be freed.
+ *   On error, NULL is returned (and errno is set), and the
+ *   nodes are freed.
+ */
+struct ec_config *
+ec_node_config_node_list_from_vargs(va_list ap);
+
+#endif