srcs += ecoli_assert.c
srcs += ecoli_completed.c
srcs += ecoli_keyval.c
+srcs += ecoli_init.c
srcs += ecoli_log.c
srcs += ecoli_malloc.c
+srcs += ecoli_murmurhash.c
srcs += ecoli_strvec.c
srcs += ecoli_test.c
srcs += ecoli_node.c
exe-y-$(O)test = $(srcs) main.c
ldflags-$(O)readline = -lreadline -ltermcap
-#exe-y-$(O)readline = $(srcs) main-readline.c
+exe-y-$(O)readline = $(srcs) main-readline.c
include $(ECOLI)/mk/ecoli-post.mk
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <ecoli_assert.h>
+
+void __ec_assert_print(bool expr, const char *expr_str, const char *format, ...)
+{
+ va_list ap;
+
+ if (expr)
+ return;
+
+ va_start(ap, format);
+ fprintf(stderr, "assertion failed: '%s' is false\n", expr_str);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ abort();
+}
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Assert API
+ *
+ * Helpers to check at runtime if a condition is true, and abort
+ * otherwise.
+ */
+
+#ifndef ECOLI_ASSERT_
+#define ECOLI_ASSERT_
+
+#include <stdbool.h>
+
+/**
+ * Abort if the condition is false.
+ *
+ * If expression is false this macro will prints an error message to
+ * standard error and terminates the program by calling abort(3).
+ *
+ * @param expr
+ * The expression to be checked.
+ * @param args
+ * The format string, optionally followed by other arguments.
+ */
+#define ec_assert_print(expr, args...) \
+ __ec_assert_print(expr, #expr, args)
+
+/* internal */
+void __ec_assert_print(bool expr, const char *expr_str,
+ const char *format, ...);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <ecoli_init.h>
+
+static struct ec_init_list init_list = TAILQ_HEAD_INITIALIZER(init_list);
+
+/* register an init function */
+void ec_init_register(struct ec_init *init)
+{
+ TAILQ_INSERT_TAIL(&init_list, init, next);
+}
+
+int ec_init(void)
+{
+ struct ec_init *init;
+
+ /* XXX sort list by priority */
+
+ TAILQ_FOREACH(init, &init_list, next) {
+ if (init->init() < 0)
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ECOLI_INIT_
+#define ECOLI_INIT_
+
+#include <sys/queue.h>
+
+#include <ecoli_log.h>
+#include <ecoli_node.h>
+
+#define EC_INIT_REGISTER(t) \
+ static void ec_init_init_##t(void); \
+ static void __attribute__((constructor, used)) \
+ ec_init_init_##t(void) \
+ { \
+ ec_init_register(&t); \
+ }
+
+/**
+ * Type of init function. Return 0 on success, -1 on error.
+ */
+typedef int (ec_init_t)(void);
+
+TAILQ_HEAD(ec_init_list, ec_init);
+
+/**
+ * A structure describing a test case.
+ */
+struct ec_init {
+ TAILQ_ENTRY(ec_init) next; /**< Next in list. */
+ ec_init_t *init; /**< Init function. */
+ unsigned int priority; /**< Priority (0=first, 99=last) */
+};
+
+/**
+ * Register an initialization function.
+ *
+ * @param init
+ * A pointer to a ec_init structure to be registered.
+ */
+void ec_init_register(struct ec_init *test);
+
+/**
+ * Initialize ecoli library
+ *
+ * Must be called before any other function.
+ *
+ * @return
+ * 0 on success, -1 on error (errno is set).
+ */
+int ec_init(void);
+
+#endif
*/
#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
+#include <ecoli_init.h>
#include <ecoli_malloc.h>
#include <ecoli_log.h>
#include <ecoli_test.h>
+#include <ecoli_murmurhash.h>
#include <ecoli_keyval.h>
+#define FACTOR 3
+
EC_LOG_TYPE_REGISTER(keyval);
+static uint32_t ec_keyval_seed;
+
struct ec_keyval_elt {
+ LIST_ENTRY(ec_keyval_elt) next;
char *key;
void *val;
+ uint32_t hash;
ec_keyval_elt_free_t free;
};
+LIST_HEAD(ec_keyval_elt_list, ec_keyval_elt);
+
struct ec_keyval {
size_t len;
- struct ec_keyval_elt *vec;
+ size_t table_size;
+ struct ec_keyval_elt_list *table;
};
struct ec_keyval *ec_keyval(void)
const char *key)
{
struct ec_keyval_elt *elt;
- size_t i;
+ uint32_t h, mask = keyval->table_size - 1;
- if (keyval == NULL || keyval->vec == NULL)
+ if (keyval == NULL || key == NULL) {
+ errno = EINVAL;
return NULL;
+ }
+ if (keyval->table_size == 0) {
+ errno = ENOENT;
+ return NULL;
+ }
- for (i = 0; i < ec_keyval_len(keyval); i++) {
- elt = &keyval->vec[i];
- if (strcmp(elt->key, key) == 0)
+ h = ec_murmurhash3(key, strlen(key), ec_keyval_seed);
+ LIST_FOREACH(elt, &keyval->table[h & mask], next) {
+ if (strcmp(elt->key, key) == 0) {
+ errno = 0;
return elt;
+ }
}
+ errno = ENOENT;
return NULL;
}
ec_free(elt->key);
if (elt->free != NULL)
elt->free(elt->val);
+ ec_free(elt);
}
bool ec_keyval_has_key(const struct ec_keyval *keyval, const char *key)
int ec_keyval_del(struct ec_keyval *keyval, const char *key)
{
struct ec_keyval_elt *elt;
- struct ec_keyval_elt *last = &keyval->vec[keyval->len - 1];
elt = ec_keyval_lookup(keyval, key);
if (elt == NULL)
- return -ENOENT;
+ return -1;
+
+ /* we could resize table here */
+ LIST_REMOVE(elt, next);
ec_keyval_elt_free(elt);
+ keyval->len--;
- if (elt != last)
- memcpy(elt, last, sizeof(*elt));
+ return 0;
+}
- keyval->len--;
+static int ec_keyval_table_resize(struct ec_keyval *keyval, size_t new_size)
+{
+ struct ec_keyval_elt_list *new_table;
+ struct ec_keyval_elt *elt;
+ size_t i;
+
+ if (new_size == 0 || (new_size & (new_size - 1))) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ new_table = ec_calloc(new_size, sizeof(*keyval->table));
+ if (new_table == NULL)
+ return -1;
+
+ for (i = 0; i < keyval->table_size; i++) {
+ while (!LIST_EMPTY(&keyval->table[i])) {
+ elt = LIST_FIRST(&keyval->table[i]);
+ LIST_REMOVE(elt, next);
+ LIST_INSERT_HEAD(&new_table[elt->hash & (new_size - 1)],
+ elt, next);
+ }
+ }
+
+ ec_free(keyval->table);
+ keyval->table = new_table;
+ keyval->table_size = new_size;
return 0;
}
int ec_keyval_set(struct ec_keyval *keyval, const char *key, void *val,
ec_keyval_elt_free_t free_cb)
{
- struct ec_keyval_elt *elt, *new_vec;
-
- assert(keyval != NULL);
- assert(key != NULL);
+ struct ec_keyval_elt *elt;
+ uint32_t h, mask;
+ size_t new_size;
+ int ret;
- ec_keyval_del(keyval, key);
+ if (keyval == NULL || key == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
- new_vec = ec_realloc(keyval->vec,
- sizeof(*keyval->vec) * (keyval->len + 1));
- if (new_vec == NULL)
- goto fail;
+ elt = ec_keyval_lookup(keyval, key);
+ if (elt != NULL) {
+ if (elt->free != NULL)
+ elt->free(elt->val);
+ elt->val = val;
+ elt->free = free_cb;
+ return 0;
+ }
- keyval->vec = new_vec;
+ if (keyval->len >= keyval->table_size) {
+ if (keyval->table_size != 0)
+ new_size = keyval->table_size << FACTOR;
+ else
+ new_size = 1 << FACTOR;
+ ret = ec_keyval_table_resize(keyval, new_size);
+ if (ret < 0)
+ goto fail;
+ }
- elt = &new_vec[keyval->len];
+ elt = ec_calloc(1, sizeof(*elt));
+ if (elt == NULL)
+ goto fail;
elt->key = ec_strdup(key);
if (elt->key == NULL)
goto fail;
-
elt->val = val;
elt->free = free_cb;
+ h = ec_murmurhash3(key, strlen(key), ec_keyval_seed);
+ elt->hash = h;
+
+ mask = keyval->table_size - 1;
+ LIST_INSERT_HEAD(&keyval->table[h & mask], elt, next);
keyval->len++;
return 0;
fail:
- if (free_cb)
+ if (free_cb != NULL)
free_cb(val);
- return -ENOMEM;
+ if (elt != NULL) {
+ ec_free(elt->key);
+ ec_free(elt);
+ }
+
+ return ret;
}
void ec_keyval_free(struct ec_keyval *keyval)
if (keyval == NULL)
return;
- for (i = 0; i < ec_keyval_len(keyval); i++) {
- elt = &keyval->vec[i];
- ec_keyval_elt_free(elt);
+ for (i = 0; i < keyval->table_size; i++) {
+ while (!LIST_EMPTY(&keyval->table[i])) {
+ elt = LIST_FIRST(&keyval->table[i]);
+ LIST_REMOVE(elt, next);
+ ec_keyval_elt_free(elt);
+ }
}
- ec_free(keyval->vec);
+ ec_free(keyval->table);
ec_free(keyval);
}
return keyval->len;
}
-void ec_keyval_dump(const struct ec_keyval *keyval, FILE *out)
+void ec_keyval_dump(FILE *out, const struct ec_keyval *keyval)
{
+ struct ec_keyval_elt *elt;
size_t i;
if (keyval == NULL) {
}
fprintf(out, "keyval:\n");
- for (i = 0; i < ec_keyval_len(keyval); i++) {
- fprintf(out, " %s: %p\n",
- keyval->vec[i].key,
- keyval->vec[i].val);
+ for (i = 0; i < keyval->table_size; i++) {
+ LIST_FOREACH(elt, &keyval->table[i], next) {
+ fprintf(out, " %s: %p\n",
+ elt->key, elt->val);
+ }
}
}
+static int ec_keyval_init_func(void)
+{
+ int fd;
+ ssize_t ret;
+
+ fd = open("/dev/urandom", 0);
+ if (fd == -1) {
+ fprintf(stderr, "failed to open /dev/urandom\n");
+ return -1;
+ }
+ ret = read(fd, &ec_keyval_seed, sizeof(ec_keyval_seed));
+ if (ret != sizeof(ec_keyval_seed)) {
+ fprintf(stderr, "failed to read /dev/urandom\n");
+ return -1;
+ }
+ close(fd);
+ return 0;
+}
+
+static struct ec_init ec_keyval_init = {
+ .init = ec_keyval_init_func,
+ .priority = 50,
+};
+
+EC_INIT_REGISTER(ec_keyval_init);
+
/* LCOV_EXCL_START */
static int ec_keyval_testcase(void)
{
struct ec_keyval *keyval;
char *val;
+ size_t i;
+ int ret;
keyval = ec_keyval();
if (keyval == NULL) {
}
EC_TEST_ASSERT(ec_keyval_len(keyval) == 0);
- ec_keyval_set(keyval, "key1", "val1", NULL);
- ec_keyval_set(keyval, "key2", ec_strdup("val2"), ec_free2);
+ ret = ec_keyval_set(keyval, "key1", "val1", NULL);
+ EC_TEST_ASSERT_STR(ret == 0, "cannot set key");
+ ret = ec_keyval_set(keyval, "key2", ec_strdup("val2"), ec_free2);
+ EC_TEST_ASSERT_STR(ret == 0, "cannot set key");
EC_TEST_ASSERT(ec_keyval_len(keyval) == 2);
val = ec_keyval_get(keyval, "key1");
val = ec_keyval_get(keyval, "key3");
EC_TEST_ASSERT(val == NULL);
- ec_keyval_set(keyval, "key1", "another_val1", NULL);
- ec_keyval_set(keyval, "key2", ec_strdup("another_val2"), ec_free2);
+ ret = ec_keyval_set(keyval, "key1", "another_val1", NULL);
+ EC_TEST_ASSERT_STR(ret == 0, "cannot set key");
+ ret = ec_keyval_set(keyval, "key2", ec_strdup("another_val2"), ec_free2);
+ EC_TEST_ASSERT_STR(ret == 0, "cannot set key");
EC_TEST_ASSERT(ec_keyval_len(keyval) == 2);
val = ec_keyval_get(keyval, "key1");
EC_TEST_ASSERT(val != NULL && !strcmp(val, "another_val1"));
val = ec_keyval_get(keyval, "key2");
EC_TEST_ASSERT(val != NULL && !strcmp(val, "another_val2"));
+ EC_TEST_ASSERT(ec_keyval_has_key(keyval, "key1"));
- ec_keyval_del(keyval, "key1");
+ ret = ec_keyval_del(keyval, "key1");
+ EC_TEST_ASSERT_STR(ret == 0, "cannot del key");
EC_TEST_ASSERT(ec_keyval_len(keyval) == 1);
+ ec_keyval_dump(stdout, NULL);
+ ec_keyval_dump(stdout, keyval);
+
+ for (i = 0; i < 100; i++) {
+ char buf[8];
+ snprintf(buf, sizeof(buf), "k%zd", i);
+ ret = ec_keyval_set(keyval, buf, "val", NULL);
+ EC_TEST_ASSERT_STR(ret == 0, "cannot set key");
+ }
ec_keyval_free(keyval);
+
return 0;
}
/* LCOV_EXCL_STOP */
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ * Simple hash table API
+ *
+ * This file provides functions to store objects in hash tables, using strings
+ * as keys.
+ */
+
#ifndef ECOLI_KEYVAL_
#define ECOLI_KEYVAL_
struct ec_keyval;
+/**
+ * Create a hash table.
+ *
+ * @return
+ * The hash table, or NULL on error (errno is set).
+ */
struct ec_keyval *ec_keyval(void);
+/**
+ * Get a value from the hash table.
+ *
+ * @param keyval
+ * The hash table.
+ * @param key
+ * The key string.
+ * @return
+ * The element if it is found, or NULL on error (errno is set).
+ * In case of success but the element is NULL, errno is set to 0.
+ */
void *ec_keyval_get(const struct ec_keyval *keyval, const char *key);
+
+/**
+ * Check if the hash table contains this key.
+ *
+ * @param keyval
+ * The hash table.
+ * @param key
+ * The key string.
+ * @return
+ * true if it contains the key, else false.
+ */
bool ec_keyval_has_key(const struct ec_keyval *keyval, const char *key);
+
+/**
+ * Delete an object from the hash table.
+ *
+ * @param keyval
+ * The hash table.
+ * @param key
+ * The key string.
+ * @return
+ * 0 on success, or -1 on error (errno is set).
+ */
int ec_keyval_del(struct ec_keyval *keyval, const char *key);
+
+/**
+ * Add/replace an object in the hash table.
+ *
+ * @param keyval
+ * The hash table.
+ * @param key
+ * The key string.
+ * @param val
+ * The pointer to be saved in the hash table.
+ * @param free_cb
+ * An optional pointer to a destructor function called when an
+ * object is destroyed (ec_keyval_del() or ec_keyval_free()).
+ * @return
+ * 0 on success, or -1 on error (errno is set).
+ */
int ec_keyval_set(struct ec_keyval *keyval, const char *key, void *val,
ec_keyval_elt_free_t free_cb);
+/**
+ * Free a hash table an all its objects.
+ *
+ * @param keyval
+ * The hash table.
+ */
void ec_keyval_free(struct ec_keyval *keyval);
+
+/**
+ * Get the length of a hash table.
+ *
+ * @param keyval
+ * The hash table.
+ * @return
+ * The length of the hash table.
+ */
size_t ec_keyval_len(const struct ec_keyval *keyval);
-void ec_keyval_dump(const struct ec_keyval *keyval, FILE *out);
+
+/**
+ * Dump a hash table.
+ *
+ * @param out
+ * The stream where the dump is sent.
+ * @param keyval
+ * The hash table.
+ */
+void ec_keyval_dump(FILE *out, const struct ec_keyval *keyval);
#endif
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <ecoli_murmurhash.h>
+
+uint32_t ec_murmurhash3(const void *key, int len, uint32_t seed)
+{
+ const uint8_t *data = (const uint8_t *)key;
+ const uint8_t *tail;
+ const int nblocks = len / 4;
+ uint32_t h1 = seed;
+ uint32_t k1;
+ const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
+ int i;
+
+ for (i = -nblocks; i; i++) {
+ k1 = blocks[i];
+
+ h1 = ec_murmurhash3_add32(h1, k1);
+ h1 = ec_murmurhash3_mix32(h1);
+ }
+
+ tail = (const uint8_t *)(data + nblocks * 4);
+ k1 = 0;
+
+ switch(len & 3) {
+ case 3: k1 ^= tail[2] << 16;
+ case 2: k1 ^= tail[1] << 8;
+ case 1: k1 ^= tail[0];
+ h1 = ec_murmurhash3_add32(h1, k1);
+ };
+
+ /* finalization */
+ h1 ^= len;
+ h1 = ec_murmurhash3_fmix32(h1);
+ return h1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * MurmurHash3 is a hash implementation that was written by Austin Appleby, and
+ * is placed in the public domain. The author hereby disclaims copyright to this
+ * source code.
+ */
+
+#ifndef ECOLI_MURMURHASH_H_
+#define ECOLI_MURMURHASH_H_
+
+#include <stdint.h>
+
+/** Hash rotation */
+static inline uint32_t ec_murmurhash_rotl32(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+/** Add 32-bit to the hash */
+static inline uint32_t ec_murmurhash3_add32(uint32_t h, uint32_t data)
+{
+ data *= 0xcc9e2d51;
+ data = ec_murmurhash_rotl32(data, 15);
+ data *= 0x1b873593;
+ h ^= data;
+ return h;
+}
+
+/** Intermediate mix */
+static inline uint32_t ec_murmurhash3_mix32(uint32_t h)
+{
+ h = ec_murmurhash_rotl32(h,13);
+ h = h * 5 +0xe6546b64;
+ return h;
+}
+
+/** Final mix: force all bits of a hash block to avalanche */
+static inline uint32_t ec_murmurhash3_fmix32(uint32_t h)
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+/**
+ * Calculate a 32-bit murmurhash3
+ *
+ * @param key
+ * The key (the unaligned variable-length array of bytes).
+ * @param len
+ * The length of the key, counting by bytes.
+ * @param seed
+ * Can be any 4-byte value initialization value.
+ * @return
+ * A 32-bit hash.
+ */
+uint32_t ec_murmurhash3(const void *key, int len, uint32_t seed);
+
+#endif /* ECOLI_MURMURHASH_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ecoli_malloc.h>
+#include <ecoli_log.h>
+#include <ecoli_test.h>
+#include <ecoli_strvec.h>
+#include <ecoli_node.h>
+#include <ecoli_parsed.h>
+#include <ecoli_completed.h>
+#include <ecoli_node_any.h>
+
+EC_LOG_TYPE_REGISTER(node_any);
+
+struct ec_node_any {
+ struct ec_node gen;
+};
+
+static int ec_node_any_parse(const struct ec_node *gen_node,
+ struct ec_parsed *state,
+ const struct ec_strvec *strvec)
+{
+ (void)gen_node;
+ (void)state;
+
+ if (ec_strvec_len(strvec) == 0)
+ return EC_PARSED_NOMATCH;
+
+ return 1;
+}
+
+static struct ec_node_type ec_node_any_type = {
+ .name = "any",
+ .parse = ec_node_any_parse,
+ .complete = ec_node_default_complete,
+ .size = sizeof(struct ec_node_any),
+};
+
+EC_NODE_TYPE_REGISTER(ec_node_any_type);
+
+/* LCOV_EXCL_START */
+static int ec_node_any_testcase(void)
+{
+ struct ec_node *node;
+ int ret = 0;
+
+ node = ec_node("any", NULL);
+ if (node == NULL) {
+ EC_LOG(EC_LOG_ERR, "cannot create node\n");
+ return -1;
+ }
+ ret |= EC_TEST_CHECK_PARSE(node, 1, "foo");
+ ret |= EC_TEST_CHECK_PARSE(node, 1, "foo", "bar");
+ ret |= EC_TEST_CHECK_PARSE(node, -1);
+ ec_node_free(node);
+
+ /* never completes */
+ node = ec_node("any", NULL);
+ if (node == NULL) {
+ EC_LOG(EC_LOG_ERR, "cannot create node\n");
+ return -1;
+ }
+ ret |= EC_TEST_CHECK_COMPLETE(node,
+ "", EC_NODE_ENDLIST,
+ EC_NODE_ENDLIST);
+ ret |= EC_TEST_CHECK_COMPLETE(node,
+ "foo", EC_NODE_ENDLIST,
+ EC_NODE_ENDLIST);
+ ec_node_free(node);
+
+ return ret;
+}
+/* LCOV_EXCL_STOP */
+
+static struct ec_test ec_node_any_test = {
+ .name = "node_any",
+ .test = ec_node_any_testcase,
+};
+
+EC_TEST_REGISTER(ec_node_any_test);
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This node always matches 1 string in the vector
+ */
+
+#ifndef ECOLI_NODE_ANY_
+#define ECOLI_NODE_ANY_
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include <ecoli_string.h>
+
+/* count the number of identical chars at the beginning of 2 strings */
+size_t ec_strcmp_count(const char *s1, const char *s2)
+{
+ size_t i = 0;
+
+ while (s1[i] && s2[i] && s1[i] == s2[i])
+ i++;
+
+ return i;
+}
+
+int ec_str_startswith(const char *s, const char *beginning)
+{
+ size_t len;
+
+ len = ec_strcmp_count(s, beginning);
+ if (beginning[len] == '\0')
+ return 1;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ECOLI_STRING_
+#define ECOLI_STRING_
+
+#include <stddef.h>
+
+/* count the number of identical chars at the beginning of 2 strings */
+size_t ec_strcmp_count(const char *s1, const char *s2);
+
+/* return 1 if 's' starts with 'beginning' */
+int ec_str_startswith(const char *s, const char *beginning);
+
+#endif
#include <errno.h>
#include <ecoli_malloc.h>
-#include <ecoli_strvec.h>
#include <ecoli_test.h>
#include <ecoli_log.h>
+#include <ecoli_vec.h>
+#include <ecoli_strvec.h>
EC_LOG_TYPE_REGISTER(strvec);
char *str;
};
-struct ec_strvec {
- size_t len;
- struct ec_strvec_elt **vec;
-};
+struct ec_strvec;
-struct ec_strvec *ec_strvec(void)
+static void ec_strvec_elt_free(void *ptr)
{
- struct ec_strvec *strvec;
+ struct ec_strvec_elt **p_elt = ptr;
+ struct ec_strvec_elt *elt = *p_elt;
- strvec = ec_calloc(1, sizeof(*strvec));
- if (strvec == NULL)
- return NULL;
+ elt->refcnt--;
+ if (elt->refcnt == 0) {
+ ec_free(elt->str);
+ ec_free(elt);
+ }
+}
+
+static void ec_strvec_elt_copy(void *dst, void *src)
+{
+ struct ec_strvec_elt **p_elt_dst = dst, **p_elt_src = src;
+ struct ec_strvec_elt *elt = *p_elt_src;
- return strvec;
+ elt->refcnt++;
+ *p_elt_dst = elt;
}
-int ec_strvec_add(struct ec_strvec *strvec, const char *s)
+struct ec_strvec *ec_strvec(void)
{
- struct ec_strvec_elt *elt, **new_vec;
+ struct ec_vec *vec;
- new_vec = ec_realloc(strvec->vec,
- sizeof(*strvec->vec) * (strvec->len + 1));
- if (new_vec == NULL)
- return -1;
+ vec = ec_vec(sizeof(struct ec_strvec_elt *), 0,
+ ec_strvec_elt_copy, ec_strvec_elt_free);
- strvec->vec = new_vec;
+ return (struct ec_strvec *)vec;
+}
+
+int ec_strvec_add(struct ec_strvec *strvec, const char *s)
+{
+ struct ec_strvec_elt *elt = NULL;
elt = ec_malloc(sizeof(*elt));
if (elt == NULL)
- return -1;
+ goto fail;
elt->str = ec_strdup(s);
- if (elt->str == NULL) {
- ec_free(elt);
- return -1;
- }
+ if (elt->str == NULL)
+ goto fail;
elt->refcnt = 1;
- new_vec[strvec->len] = elt;
- strvec->len++;
+ if (ec_vec_add_ptr((struct ec_vec *)strvec, elt) < 0)
+ goto fail;
+
return 0;
+
+fail:
+ ec_free(elt);
+ return -1;
}
struct ec_strvec *ec_strvec_ndup(const struct ec_strvec *strvec, size_t off,
size_t len)
{
- struct ec_strvec *copy = NULL;
- size_t i;
-
- if (off + len > ec_strvec_len(strvec)) {
- errno = EINVAL;
- return NULL;
- }
-
- copy = ec_strvec();
- if (copy == NULL)
- goto fail;
-
- if (len == 0)
- return copy;
-
- copy->vec = ec_calloc(len, sizeof(*copy->vec));
- if (copy->vec == NULL)
- goto fail;
-
- for (i = 0; i < len; i++) {
- copy->vec[i] = strvec->vec[i + off];
- copy->vec[i]->refcnt++;
- copy->len++;
- }
-
- return copy;
-
-fail:
- ec_strvec_free(copy);
- return NULL;
+ return (struct ec_strvec *)ec_vec_ndup((struct ec_vec *)strvec,
+ off, len);
}
struct ec_strvec *ec_strvec_dup(const struct ec_strvec *strvec)
{
- return ec_strvec_ndup(strvec, 0, ec_strvec_len(strvec));
+ return (struct ec_strvec *)ec_vec_dup((struct ec_vec *)strvec);
}
void ec_strvec_free(struct ec_strvec *strvec)
{
- struct ec_strvec_elt *elt;
- size_t i;
-
- if (strvec == NULL)
- return;
-
- for (i = 0; i < ec_strvec_len(strvec); i++) {
- elt = strvec->vec[i];
- elt->refcnt--;
- if (elt->refcnt == 0) {
- ec_free(elt->str);
- ec_free(elt);
- }
- }
-
- ec_free(strvec->vec);
- ec_free(strvec);
+ ec_vec_free((struct ec_vec *)strvec);
}
size_t ec_strvec_len(const struct ec_strvec *strvec)
{
- if (strvec == NULL)
- return 0;
-
- return strvec->len;
+ return ec_vec_len((struct ec_vec *)strvec);
}
const char *ec_strvec_val(const struct ec_strvec *strvec, size_t idx)
{
- if (strvec == NULL || idx >= strvec->len)
+ struct ec_strvec_elt *elt;
+
+ if (ec_vec_get(&elt, (struct ec_vec *)strvec, idx) < 0)
return NULL;
- return strvec->vec[idx]->str;
+ return elt->str;
}
void ec_strvec_dump(FILE *out, const struct ec_strvec *strvec)
{
+ const char *s;
size_t i;
if (strvec == NULL) {
return;
}
- fprintf(out, "strvec (len=%zu) [", strvec->len);
+ fprintf(out, "strvec (len=%zu) [", ec_strvec_len(strvec));
for (i = 0; i < ec_strvec_len(strvec); i++) {
+ s = ec_strvec_val(strvec, i);
if (i == 0)
- fprintf(out, "%s", strvec->vec[i]->str);
+ fprintf(out, "%s", s);
else
- fprintf(out, ", %s", strvec->vec[i]->str);
+ fprintf(out, ", %s", s);
}
fprintf(out, "]\n");
EC_LOG_TYPE_REGISTER(test);
-/* register a driver */
+/* register a test case */
void ec_test_register(struct ec_test *test)
{
TAILQ_INSERT_TAIL(&test_list, test, next);
EC_LOG(EC_LOG_ERR, "%s:%d: error: " fmt "\n", \
__FILE__, __LINE__, ##__VA_ARGS__); \
-#define EC_TEST_ASSERT(cond) \
+/* XXX this is not an assert, it does not abort */
+#define EC_TEST_ASSERT_STR(cond, fmt, ...) \
do { \
if (!(cond)) \
- EC_TEST_ERR("assertion failure: " #cond); \
+ EC_TEST_ERR("assert failure: (" #cond ") " fmt, \
+ ##__VA_ARGS__); \
} while (0)
+#define EC_TEST_ASSERT(cond) EC_TEST_ASSERT_STR(cond, "")
+
/* node, input, [expected1, expected2, ...] */
#define EC_TEST_CHECK_PARSE(node, args...) ({ \
int ret_ = ec_test_check_parse(node, args, EC_NODE_ENDLIST); \
}
vec->vec = new_vec;
- if (vec->copy)
- vec->copy(get_obj(vec, vec->len), ptr);
- else
- memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
+ memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
vec->len++;
return 0;
size_t ec_vec_len(const struct ec_vec *vec)
{
+ if (vec == NULL)
+ return 0;
+
return vec->len;
}
int ec_vec_get(void *ptr, const struct ec_vec *vec, size_t idx)
{
- if (vec == NULL || idx >= vec->len)
- return -EINVAL;
+ if (vec == NULL || idx >= vec->len) {
+ errno = EINVAL;
+ return -1;
+ }
- if (vec->copy)
- vec->copy(ptr, get_obj(vec, idx));
- else
- memcpy(ptr, get_obj(vec, idx), vec->elt_size);
+ memcpy(ptr, get_obj(vec, idx), vec->elt_size);
return 0;
}
/* if NULL, default does nothing */
typedef void (*ec_vec_elt_free_t)(void *ptr);
+
/* if NULL, default is:
* memcpy(dst, src, vec->elt_size)
*/
#define _GNU_SOURCE /* for asprintf */
#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
#include <assert.h>
#include <readline/readline.h>
#include <readline/history.h>
+#include <ecoli_init.h>
#include <ecoli_node.h>
#include <ecoli_parsed.h>
#include <ecoli_completed.h>
struct ec_parsed *p;
char *line;
+ if (ec_init() < 0) {
+ fprintf(stderr, "cannot init ecoli: %s\n", strerror(errno));
+ return 1;
+ }
+
if (create_commands() < 0)
return 1;
#include <getopt.h>
#include <limits.h>
#include <execinfo.h>
+#include <errno.h>
+#include <ecoli_init.h>
#include <ecoli_log.h>
#include <ecoli_test.h>
#include <ecoli_malloc.h>
srandom(seed);
+ if (ec_init() < 0) {
+ fprintf(stderr, "cannot init ecoli: %s\n", strerror(errno));
+ return 1;
+ }
ec_log_fct_register(debug_log, NULL);
/* register a new malloc to track memleaks */
TAILQ_INIT(&debug_alloc_hdr_list);
if (ec_malloc_register(debug_malloc, debug_free, debug_realloc) < 0) {
EC_LOG(EC_LOG_ERR, "cannot register new malloc\n");
- return -1;
+ return 1;
}
ret = 0;