diff options
author | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-04-15 12:56:54 -0300 |
---|---|---|
committer | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-04-15 12:56:54 -0300 |
commit | 0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b (patch) | |
tree | 212c4d2ac7e269cc9f03f2240e36f865d4ce2493 | |
parent | a8e0fedb3f12ed1ceda7879944606c8e1e7d4a08 (diff) | |
download | blogc-0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b.tar.gz blogc-0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b.tar.bz2 blogc-0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b.zip |
initial structure
-rw-r--r-- | .gitignore | 51 | ||||
-rw-r--r-- | Makefile.am | 149 | ||||
-rwxr-xr-x | autogen.sh | 6 | ||||
-rw-r--r-- | configure.ac | 107 | ||||
-rw-r--r-- | m4/.keep | 0 | ||||
-rw-r--r-- | src/main.c | 21 | ||||
-rw-r--r-- | src/utils/slist.c | 64 | ||||
-rw-r--r-- | src/utils/strings.c | 277 | ||||
-rw-r--r-- | src/utils/trie.c | 193 | ||||
-rw-r--r-- | src/utils/utils.h | 71 | ||||
-rw-r--r-- | tests/check_utils.c | 790 |
11 files changed, 1721 insertions, 8 deletions
@@ -1,14 +1,49 @@ -# http://www.gnu.org/software/automake +# Object files +*.o +*.ko -Makefile.in +# Libraries +*.lib +*.a -# http://www.gnu.org/software/autoconf +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib -/autom4te.cache +# Executables +*.exe +*.out +*.app + +# Autotools +Makefile +Makefile.in +.deps +.libs +*.la +*.lo /aclocal.m4 -/compile /configure -/depcomp -/install-sh -/missing +/config.* +/autom4te.cache +/libtool /stamp-h1 +.dirstamp +/build-aux/* + +# installed .m4 files +/m4/*.m4 + +# blogc +/blogc + +# tests +/tests/check_utils + +# leg generated source +/src/template/parser-grammar.c + +# tarballs +blogc-*.tar.* diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..4e213e5 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,149 @@ +## Autotools settings + +ACLOCAL_AMFLAGS = -I m4 + +AM_DISTCHECK_CONFIGURE_FLAGS = \ + --enable-examples \ + --enable-cmocka \ + --disable-leg \ + --disable-valgrind + + +## File listings + +EXTRA_DIST = \ + autogen.sh \ + README.md \ + $(NULL) + +CLEANFILES = \ + $(NULL) + +noinst_HEADERS = \ + src/utils/utils.h \ + $(NULL) + +noinst_LTLIBRARIES = \ + libblogc.la \ + $(NULL) + +noinst_PROGRAMS = \ + $(NULL) + +bin_PROGRAMS = \ + blogc \ + $(NULL) + +check_PROGRAMS = \ + $(NULL) + + +libblogc_la_SOURCES = \ + src/utils/slist.c \ + src/utils/strings.c \ + src/utils/trie.c \ + $(NULL) + +libblogc_la_CFLAGS = \ + $(AM_CFLAGS) \ + -I$(top_srcdir)/src \ + $(NULL) + +libblogc_la_LIBADD = \ + $(NULL) + +if USE_LEG +endif + +blogc_SOURCES = \ + src/main.c \ + $(NULL) + +blogc_CFLAGS = \ + $(AM_CFLAGS) \ + -I$(top_srcdir)/src \ + $(NULL) + +blogc_LDADD = \ + libblogc.la \ + $(NULL) + + +## Build rules: examples + +if BUILD_EXAMPLES + +noinst_PROGRAMS += \ + $(NULL) + +endif + + +## Build rules: tests + +if USE_CMOCKA + +check_PROGRAMS += \ + tests/check_utils \ + $(NULL) + +tests_check_utils_SOURCES = \ + tests/check_utils.c \ + $(NULL) + +tests_check_utils_CFLAGS = \ + $(CMOCKA_CFLAGS) \ + $(NULL) + +tests_check_utils_LDFLAGS = \ + -no-install + +tests_check_utils_LDADD = \ + $(CMOCKA_LIBS) \ + libblogc.la \ + $(NULL) + +endif + +TESTS = \ + $(check_PROGRAMS) + + +## Helpers: Valgrind runners + +if USE_VALGRIND +valgrind: all + $(MAKE) check TESTS_ENVIRONMENT=" \ + G_SLICE=always-malloc \ + G_DEBUG=gc-friendly \ + $(LIBTOOL) \ + --mode=execute \ + $(VALGRIND) \ + --tool=memcheck \ + --leak-check=full \ + --leak-resolution=high \ + --num-callers=20 \ + --show-possibly-lost=no" + +valgrind-ci: all clean-local + $(MAKE) check TESTS_ENVIRONMENT=" \ + G_SLICE=always-malloc \ + G_DEBUG=gc-friendly \ + $(LIBTOOL) \ + --mode=execute \ + $(VALGRIND) \ + --tool=memcheck \ + --xml=yes \ + --xml-file=valgrind-%p.xml \ + --leak-check=full \ + --leak-resolution=high \ + --num-callers=20 \ + --show-possibly-lost=no" +endif + + +# Helpers: Cleanup of helper files + +clean-local: + -rm -rf $(top_builddir)/doc/build/ + -rm -rf $(top_builddir)/valgrind-*.xml diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..91726d6 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +autoreconf \ + --warnings=all \ + --install \ + --force diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..49e2006 --- /dev/null +++ b/configure.ac @@ -0,0 +1,107 @@ +AC_PREREQ([2.69]) + +AC_INIT([blogc], [0], [https://github.com/rafaelmartins/blogc], [blogc], [http://blogc.org]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([1.13 foreign dist-bzip2 dist-xz subdir-objects serial-tests]) +AC_CONFIG_HEADERS([config.h]) +AM_SILENT_RULES([yes]) +AM_MAINTAINER_MODE([enable]) + +LT_INIT + +AC_PROG_CC_C99 +AS_IF([test "x$ac_cv_prog_cc_c99" = "xno"], [ + AC_MSG_ERROR([no C99 compiler found, blogc requires a C99 compiler.]) +]) + +AC_ARG_ENABLE([examples], AS_HELP_STRING([--enable-examples], [build examples])) +AS_IF([test "x$enable_examples" = "xyes"], [ + build_examples=yes + EXAMPLES="enabled" +], [ + build_examples=no + EXAMPLES="disabled" +]) +AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" = "xyes"]) + +AC_ARG_ENABLE([valgrind], AS_HELP_STRING([--disable-valgrind], + [ignore presence of valgrind])) +AS_IF([test "x$enable_valgrind" != "xno"], [ + AC_PATH_PROG([valgrind], [valgrind]) + AS_IF([test "x$ac_cv_path_valgrind" = "x"], [ + have_valgrind=no + ], [ + have_valgrind=yes + ]) +]) +AS_IF([test "x$have_valgrind" = "xyes"], , [ + AS_IF([test "x$enable_valgrind" = "xyes"], [ + AC_MSG_ERROR([valgrind requested but not found]) + ]) +]) +AM_CONDITIONAL([USE_VALGRIND], [test "x$have_valgrind" = "xyes"]) +VALGRIND="$ac_cv_path_valgrind" +AC_SUBST(VALGRIND) + +AC_ARG_ENABLE([leg], AS_HELP_STRING([--disable-leg], + [ignore presence of peg/leg and disable parser grammar regeneration])) +AS_IF([test "x$enable_leg" != "xno"], [ + AC_PATH_PROG([leg], [leg]) + AS_IF([test "x$ac_cv_path_leg" = "x"], [ + have_leg=no + ], [ + have_leg=yes + ]) +]) +AS_IF([test "x$have_leg" = "xyes"], , [ + AS_IF([test "x$enable_leg" = "xyes"], [ + AC_MSG_ERROR([peg/leg requested but not found]) + ]) +]) +AM_CONDITIONAL([USE_LEG], [test "x$have_leg" = "xyes"]) +LEG="$ac_cv_path_leg" +AC_SUBST(LEG) + +AC_ARG_ENABLE([cmocka], AS_HELP_STRING([--disable-cmocka], + [ignore presence of cmocka. this will disable unit tests])) +AS_IF([test "x$enable_cmocka" != "xno"], [ + PKG_PROG_PKG_CONFIG + PKG_CHECK_MODULES([CMOCKA], [cmocka], [ + CMOCKA="enabled" + have_cmocka=yes + ], [ + CMOCKA="disabled" + have_cmocka=no + ]) +]) +AS_IF([test "x$have_cmocka" = "xyes"], , [ + AS_IF([test "x$enable_cmocka" = "xyes"], [ + AC_MSG_ERROR([cmocka requested but not found]) + ]) +]) +AM_CONDITIONAL([USE_CMOCKA], [test "x$have_cmocka" = "xyes"]) + +AC_CONFIG_FILES([ + Makefile +]) +AC_OUTPUT + +AS_ECHO(" + ==== ${PACKAGE_STRING} ==== + + prefix: ${prefix} + exec_prefix: ${exec_prefix} + bindir: ${bindir} + + compiler: ${CC} + cflags: ${CFLAGS} + ldflags: ${LDFLAGS} + + examples: ${EXAMPLES} + + valgrind: ${VALGRIND} + leg: ${LEG} + cmocka: ${CMOCKA} +") diff --git a/m4/.keep b/m4/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/m4/.keep diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f989f62 --- /dev/null +++ b/src/main.c @@ -0,0 +1,21 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> + + +int +main(int argc, char **argv) +{ + printf("Hello, World!\n"); + return 0; +} diff --git a/src/utils/slist.c b/src/utils/slist.c new file mode 100644 index 0000000..e0c1a44 --- /dev/null +++ b/src/utils/slist.c @@ -0,0 +1,64 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#include <stdlib.h> +#include "utils.h" + + +b_slist_t* +b_slist_append(b_slist_t *l, void *data) +{ + b_slist_t *node = malloc(sizeof(b_slist_t)); + if (node == NULL) { + l = NULL; + return l; + } + node->data = data; + node->next = NULL; + if (l == NULL) + l = node; + else { + b_slist_t *tmp; + for (tmp = l; tmp->next != NULL; tmp = tmp->next); + tmp->next = node; + } + return l; +} + + +void +b_slist_free_full(b_slist_t *l, void (*free_func)(void *ptr)) +{ + while (l != NULL) { + b_slist_t *tmp = l->next; + free_func(l->data); + free(l); + l = tmp; + } +} + + +void +b_slist_free(b_slist_t *l) +{ + while (l != NULL) { + b_slist_t *tmp = l->next; + free(l); + l = tmp; + } +} + + +unsigned int +b_slist_length(b_slist_t *l) +{ + unsigned int i; + b_slist_t *tmp; + for (tmp = l, i = 0; tmp != NULL; tmp = tmp->next, i++); + return i; +} diff --git a/src/utils/strings.c b/src/utils/strings.c new file mode 100644 index 0000000..b3a19cc --- /dev/null +++ b/src/utils/strings.c @@ -0,0 +1,277 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#include <ctype.h> +#include <string.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include "utils.h" + + +char* +b_strdup(const char *s) +{ + if (s == NULL) + return NULL; + size_t l = strlen(s); + char *tmp = malloc(l + 1); + if (tmp == NULL) + return NULL; + memcpy(tmp, s, l + 1); + return tmp; +} + + +char* +b_strndup(const char *s, size_t n) +{ + if (s == NULL) + return NULL; + size_t l = strnlen(s, n); + char *tmp = malloc(l + 1); + if (tmp == NULL) + return NULL; + memcpy(tmp, s, l); + tmp[l] = '\0'; + return tmp; +} + + +char* +b_strdup_vprintf(const char *format, va_list ap) +{ + va_list ap2; + va_copy(ap2, ap); + int l = vsnprintf(NULL, 0, format, ap2); + va_end(ap2); + if (l < 0) + return NULL; + char *tmp = malloc(l + 1); + if (!tmp) + return NULL; + int l2 = vsnprintf(tmp, l + 1, format, ap); + if (l2 < 0) + return NULL; + return tmp; +} + + +char* +b_strdup_printf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + char *tmp = b_strdup_vprintf(format, ap); + va_end(ap); + return tmp; +} + + +bool +b_str_starts_with(const char *str, const char *prefix) +{ + int str_l = strlen(str); + int str_lp = strlen(prefix); + if (str_lp > str_l) + return false; + return strncmp(str, prefix, str_lp) == 0; +} + + +bool +b_str_ends_with(const char *str, const char *suffix) +{ + int str_l = strlen(str); + int str_ls = strlen(suffix); + if (str_ls > str_l) + return false; + return strcmp(str + str_l - str_ls, suffix) == 0; +} + + +char* +b_str_strip(char *str) +{ + if (str == NULL) + return str; + int i; + size_t str_len = strlen(str); + for (i = str_len - 1; i >= 0; i--) { + if (!isspace(str[i])) { + str[i + 1] = '\0'; + break; + } + } + str_len = strlen(str); + for (i = 0; i < str_len; i++) { + if (!isspace(str[i])) { + str = str + i; + break; + } + } + return str; +} + + +char** +b_str_split(const char *str, char c, unsigned int max_pieces) +{ + if (!str) + return NULL; + char **rv = malloc(sizeof(char*)); + unsigned int i, start = 0, count = 0; + for (i = 0; i < strlen(str) + 1; i++) { + if (str[0] == '\0') + break; + if ((str[i] == c && (!max_pieces || count + 1 < max_pieces)) || str[i] == '\0') { + rv = realloc(rv, (count + 1) * sizeof(char*)); + rv[count] = malloc(i - start + 1); + memcpy(rv[count], str + start, i - start); + rv[count++][i - start] = '\0'; + start = i + 1; + } + } + rv = realloc(rv, (count + 1) * sizeof(char*)); + rv[count] = NULL; + return rv; +} + + +char* +b_str_replace(const char *str, const char search, const char *replace) +{ + char **pieces = b_str_split(str, search, 0); + if (pieces == NULL) + return NULL; + char* rv = b_strv_join((const char**) pieces, replace); + b_strv_free(pieces); + return rv; +} + + +void +b_strv_free(char **strv) +{ + if (strv == NULL) + return; + unsigned int i; + for (i = 0; strv[i] != NULL; i++) + free(strv[i]); + free(strv); +} + + +char* +b_strv_join(const char **strv, const char *separator) +{ + if (strv == NULL) + return NULL; + unsigned int i = 0; + b_string_t *str = b_string_new(); + for (i = 0; strv[i] != NULL; i++) { + str = b_string_append(str, strv[i]); + if (strv[i+1] != NULL) + str = b_string_append(str, separator); + } + return b_string_free(str, false); +} + + +unsigned int +b_strv_length(char **strv) +{ + if (!strv) + return 0; + unsigned int i; + for (i = 0; strv[i] != NULL; i++); + return i; +} + + +b_string_t* +b_string_new(void) +{ + b_string_t* rv = malloc(sizeof(b_string_t)); + rv->str = NULL; + rv->len = 0; + rv->allocated_len = 0; + + // initialize with empty string + rv = b_string_append(rv, ""); + + return rv; +} + + +char* +b_string_free(b_string_t *str, bool free_str) +{ + char *rv = NULL; + if (free_str) + free(str->str); + else + rv = str->str; + free(str); + return rv; +} + + +b_string_t* +b_string_append_len(b_string_t *str, const char *suffix, size_t len) +{ + if (suffix == NULL) + return str; + size_t old_len = str->len; + str->len += len; + if (str->len + 1 > str->allocated_len) { + str->allocated_len = (((str->len + 1) / B_STRING_CHUNK_SIZE) + 1) * B_STRING_CHUNK_SIZE; + str->str = realloc(str->str, str->allocated_len); + } + memcpy(str->str + old_len, suffix, len); + str->str[str->len] = '\0'; + return str; +} + + +b_string_t* +b_string_append(b_string_t *str, const char *suffix) +{ + if (suffix == NULL) + return str; + return b_string_append_len(str, suffix, strlen(suffix)); +} + + +b_string_t* +b_string_append_c(b_string_t *str, char c) +{ + size_t old_len = str->len; + str->len += 1; + if (str->len + 1 > str->allocated_len) { + str->allocated_len = (((str->len + 1) / B_STRING_CHUNK_SIZE) + 1) * B_STRING_CHUNK_SIZE; + str->str = realloc(str->str, str->allocated_len); + } + str->str[old_len] = c; + str->str[str->len] = '\0'; + return str; +} + + +b_string_t* +b_string_append_printf(b_string_t *str, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + char *tmp = b_strdup_vprintf(format, ap); + va_end(ap); + str = b_string_append(str, tmp); + free(tmp); + return str; +} diff --git a/src/utils/trie.c b/src/utils/trie.c new file mode 100644 index 0000000..f447860 --- /dev/null +++ b/src/utils/trie.c @@ -0,0 +1,193 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "utils.h" + + +b_trie_t* +b_trie_new(void (*free_func)(void *ptr)) +{ + b_trie_t *trie = malloc(sizeof(b_trie_t)); + trie->root = NULL; + trie->free_func = free_func; + return trie; +} + + +static void +b_trie_free_node(b_trie_t *trie, b_trie_node_t *node) +{ + if (node == NULL) + return; + if (node->data != NULL && trie->free_func != NULL) + trie->free_func(node->data); + b_trie_free_node(trie, node->next); + b_trie_free_node(trie, node->child); + free(node); +} + + +void +b_trie_free(b_trie_t *trie) +{ + b_trie_free_node(trie, trie->root); + free(trie); +} + + +void +b_trie_insert(b_trie_t *trie, const char *key, void *data) +{ + if (data == NULL || key == NULL) + return; + + b_trie_node_t *parent = NULL; + b_trie_node_t *previous; + b_trie_node_t *current; + b_trie_node_t *tmp; + + while (1) { + + if (trie->root == NULL || (parent != NULL && parent->child == NULL)) { + current = malloc(sizeof(b_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + if (trie->root == NULL) + trie->root = current; + else + parent->child = current; + parent = current; + goto clean; + } + + tmp = parent == NULL ? trie->root : parent->child; + previous = NULL; + + while (tmp != NULL && tmp->key != *key) { + previous = tmp; + tmp = tmp->next; + } + + parent = tmp; + + if (previous == NULL || parent != NULL) + goto clean; + + current = malloc(sizeof(b_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + previous->next = current; + parent = current; + +clean: + if (*key == '\0') { + parent->data = data; + break; + } + key++; + } +} + + +void* +b_trie_lookup(b_trie_t *trie, const char *key) +{ + if (trie->root == NULL || key == NULL) + return NULL; + + b_trie_node_t *parent = trie->root; + b_trie_node_t *tmp; + while (1) { + for (tmp = parent; tmp != NULL; tmp = tmp->next) { + + if (tmp->key == *key) { + if (tmp->key == '\0') + return tmp->data; + parent = tmp->child; + break; + } + } + if (tmp == NULL) + return NULL; + + if (*key == '\0') + break; + key++; + } + return NULL; +} + + +static void +b_trie_size_node(b_trie_node_t *node, unsigned int *count) +{ + if (node == NULL) + return; + + if (node->key == '\0') + (*count)++; + + b_trie_size_node(node->next, count); + b_trie_size_node(node->child, count); +} + + +unsigned int +b_trie_size(b_trie_t *trie) +{ + if (trie == NULL) + return 0; + + unsigned int count = 0; + b_trie_size_node(trie->root, &count); + return count; +} + + +static void +b_trie_foreach_node(b_trie_node_t *node, b_string_t *str, void (*func)(const char *key, void *data)) +{ + if (node == NULL) + return; + + if (node->key == '\0') { + func(str->str, node->data); + b_string_free(str, true); + } + + if (node->child != NULL) { + b_string_t *child = b_string_new(); + child = b_string_append(child, str->str); + child = b_string_append_c(child, node->key); + b_trie_foreach_node(node->child, child, func); + } + + if (node->next != NULL) + b_trie_foreach_node(node->next, str, func); + + if (node->child != NULL && node->next == NULL) + b_string_free(str, true); +} + + +void +b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data)) +{ + if (trie->root == NULL) + return; + + b_string_t *str = b_string_new(); + b_trie_foreach_node(trie->root, str, func); +} diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..20259d8 --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,71 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifndef _UTILS_UTILS_H +#define _UTILS_UTILS_H + +#include <stdbool.h> +#include <stdarg.h> + +#define B_STRING_CHUNK_SIZE 128 + +typedef struct _b_slist_t { + struct _b_slist_t *next; + void *data; +} b_slist_t; + +typedef struct _b_string_t { + char *str; + size_t len; + size_t allocated_len; +} b_string_t; + +typedef struct _b_trie_node_t { + char key; + void *data; + struct _b_trie_node_t *next, *child; +} b_trie_node_t; + +typedef struct _b_trie_t { + b_trie_node_t *root; + void (*free_func)(void *ptr); +} b_trie_t; + +b_slist_t* b_slist_append(b_slist_t *l, void *data); +void b_slist_free_full(b_slist_t *l, void (*free_func)(void *ptr)); +void b_slist_free(b_slist_t *l); +unsigned int b_slist_length(b_slist_t *l); + +char* b_strdup(const char *s); +char* b_strndup(const char *s, size_t n); +char* b_strdup_vprintf(const char *format, va_list ap); +char* b_strdup_printf(const char *format, ...); +bool b_str_starts_with(const char *str, const char *prefix); +bool b_str_ends_with(const char *str, const char *suffix); +char* b_str_strip(char *str); +char** b_str_split(const char *str, char c, unsigned int max_pieces); +char* b_str_replace(const char *str, const char search, const char *replace); +void b_strv_free(char **strv); +char* b_strv_join(const char **strv, const char *separator); +unsigned int b_strv_length(char **strv); + +b_string_t* b_string_new(void); +char* b_string_free(b_string_t *str, bool free_str); +b_string_t* b_string_append_len(b_string_t *str, const char *suffix, size_t len); +b_string_t* b_string_append(b_string_t *str, const char *suffix); +b_string_t* b_string_append_c(b_string_t *str, char c); +b_string_t* b_string_append_printf(b_string_t *str, const char *format, ...); + +b_trie_t* b_trie_new(void (*free_func)(void *ptr)); +void b_trie_free(b_trie_t *trie); +void b_trie_insert(b_trie_t *trie, const char *key, void *data); +void* b_trie_lookup(b_trie_t *trie, const char *key); +unsigned int b_trie_size(b_trie_t *trie); +void b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data)); + +#endif /* _UTILS_UTILS_H */ diff --git a/tests/check_utils.c b/tests/check_utils.c new file mode 100644 index 0000000..5f4cb9f --- /dev/null +++ b/tests/check_utils.c @@ -0,0 +1,790 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <stdlib.h> + +#include "../src/utils/utils.h" + + +static void +test_slist_append(void **state) +{ + b_slist_t *l = NULL; + l = b_slist_append(l, (void*) b_strdup("bola")); + assert_non_null(l); + assert_string_equal(l->data, "bola"); + assert_null(l->next); + l = b_slist_append(l, (void*) b_strdup("guda")); + assert_non_null(l); + assert_string_equal(l->data, "bola"); + assert_non_null(l->next); + assert_string_equal(l->next->data, "guda"); + assert_null(l->next->next); + b_slist_free_full(l, free); +} + + +static void +test_slist_free(void **state) +{ + b_slist_t *l = NULL; + char *t1 = b_strdup("bola"); + char *t2 = b_strdup("guda"); + char *t3 = b_strdup("chunda"); + l = b_slist_append(l, (void*) t1); + l = b_slist_append(l, (void*) t2); + l = b_slist_append(l, (void*) t3); + b_slist_free(l); + assert_string_equal(t1, "bola"); + assert_string_equal(t2, "guda"); + assert_string_equal(t3, "chunda"); + free(t1); + free(t2); + free(t3); +} + + +static void +test_slist_length(void **state) +{ + b_slist_t *l = NULL; + l = b_slist_append(l, (void*) b_strdup("bola")); + l = b_slist_append(l, (void*) b_strdup("guda")); + l = b_slist_append(l, (void*) b_strdup("chunda")); + assert_int_equal(b_slist_length(l), 3); + b_slist_free_full(l, free); +} + + +static void +test_strdup(void **state) +{ + char *str = b_strdup("bola"); + assert_string_equal(str, "bola"); + free(str); + str = b_strdup(NULL); + assert_null(str); +} + + +static void +test_strndup(void **state) +{ + char *str = b_strndup("bolaguda", 4); + assert_string_equal(str, "bola"); + free(str); + str = b_strndup("bolaguda", 30); + assert_string_equal(str, "bolaguda"); + free(str); + str = b_strndup("bolaguda", 8); + assert_string_equal(str, "bolaguda"); + free(str); + str = b_strdup(NULL); + assert_null(str); +} + + +static void +test_strdup_printf(void **state) +{ + char *str = b_strdup_printf("bola"); + assert_string_equal(str, "bola"); + free(str); + str = b_strdup_printf("bola, %s", "guda"); + assert_string_equal(str, "bola, guda"); + free(str); +} + + +static void +test_str_starts_with(void **state) +{ + assert_true(b_str_starts_with("bolaguda", "bola")); + assert_true(b_str_starts_with("bola", "bola")); + assert_false(b_str_starts_with("gudabola", "bola")); + assert_false(b_str_starts_with("guda", "bola")); + assert_false(b_str_starts_with("bola", "bolaguda")); +} + + +static void +test_str_ends_with(void **state) +{ + assert_true(b_str_ends_with("bolaguda", "guda")); + assert_true(b_str_ends_with("bola", "bola")); + assert_false(b_str_ends_with("gudabola", "guda")); + assert_false(b_str_ends_with("guda", "bola")); + assert_false(b_str_ends_with("bola", "gudabola")); +} + + +static void +test_str_strip(void **state) +{ + char *str = b_strdup(" \tbola\n \t"); + assert_string_equal(b_str_strip(str), "bola"); + free(str); + str = b_strdup("guda"); + assert_string_equal(b_str_strip(str), "guda"); + free(str); + assert_null(b_str_strip(NULL)); +} + + +static void +test_str_split(void **state) +{ + char **strv = b_str_split("bola:guda:chunda", ':', 0); + assert_string_equal(strv[0], "bola"); + assert_string_equal(strv[1], "guda"); + assert_string_equal(strv[2], "chunda"); + assert_null(strv[3]); + b_strv_free(strv); + strv = b_str_split("bola:guda:chunda", ':', 2); + assert_string_equal(strv[0], "bola"); + assert_string_equal(strv[1], "guda:chunda"); + assert_null(strv[2]); + b_strv_free(strv); + strv = b_str_split("bola:guda:chunda", ':', 1); + assert_string_equal(strv[0], "bola:guda:chunda"); + assert_null(strv[1]); + b_strv_free(strv); + strv = b_str_split("", ':', 1); + assert_null(strv[0]); + b_strv_free(strv); + assert_null(b_str_split(NULL, ':', 0)); +} + + +static void +test_str_replace(void **state) +{ + char *str = b_str_replace("bolao", 'o', "zaz"); + assert_string_equal(str, "bzazlazaz"); + free(str); + str = b_str_replace("bolao", 'b', "zaz"); + assert_string_equal(str, "zazolao"); + free(str); +} + + +static void +test_strv_join(void **state) +{ + const char *pieces[] = {"guda","bola", "chunda", NULL}; + char *str = b_strv_join(pieces, ":"); + assert_string_equal(str, "guda:bola:chunda"); + free(str); + const char *pieces2[] = {NULL}; + str = b_strv_join(pieces2, ":"); + assert_string_equal(str, ""); + free(str); + assert_null(b_strv_join(NULL, ":")); +} + + +static void +test_strv_length(void **state) +{ + char *pieces[] = {"guda","bola", "chunda", NULL}; + assert_int_equal(b_strv_length(pieces), 3); + char *pieces2[] = {NULL}; + assert_int_equal(b_strv_length(pieces2), 0); + assert_int_equal(b_strv_length(NULL), 0); +} + + +static void +test_string_new(void **state) +{ + b_string_t *str = b_string_new(); + assert_non_null(str); + assert_string_equal(str->str, ""); + assert_int_equal(str->len, 0); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); +} + + +static void +test_string_free(void **state) +{ + b_string_t *str = b_string_new(); + free(str->str); + str->str = b_strdup("bola"); + str->len = 4; + str->allocated_len = B_STRING_CHUNK_SIZE; + char *tmp = b_string_free(str, false); + assert_string_equal(tmp, "bola"); + free(tmp); +} + + +static void +test_string_append_len(void **state) +{ + b_string_t *str = b_string_new(); + str = b_string_append_len(str, "guda", 4); + assert_non_null(str); + assert_string_equal(str->str, "guda"); + assert_int_equal(str->len, 4); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); + str = b_string_new(); + str = b_string_append_len(str, "guda", 4); + str = b_string_append_len(str, "bola", 4); + assert_non_null(str); + assert_string_equal(str->str, "gudabola"); + assert_int_equal(str->len, 8); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); + str = b_string_new(); + str = b_string_append_len(str, "guda", 3); + str = b_string_append_len(str, "bola", 4); + assert_non_null(str); + assert_string_equal(str->str, "gudbola"); + assert_int_equal(str->len, 7); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); + str = b_string_new(); + str = b_string_append_len(str, "guda", 4); + str = b_string_append_len(str, + "cwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcw" + "nnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwa" + "xfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevaz" + "dxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcec" + "hgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbc" + "sbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnd" + "dxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnr" + "ftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtg" + "okxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexf", 600); + str = b_string_append_len(str, NULL, 0); + str = b_string_append_len(str, + "cwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcw" + "nnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwa" + "xfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevaz" + "dxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcec" + "hgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbc" + "sbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnd" + "dxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnr" + "ftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtg" + "okxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexf", 600); + assert_non_null(str); + assert_string_equal(str->str, + "gudacwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjid" + "zkcwnnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtax" + "jiwaxfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqv" + "evazdxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywh" + "qcechgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxj" + "rsbcsbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqd" + "atnddxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvw" + "srnrftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsf" + "nwtgokxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexfcwlwmwxxmvjnwtidm" + "jehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcwnnqhxhneolbwqlctc" + "xmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwaxfhfyzymtffusoqyw" + "aruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevazdxrewtgapkompnvii" + "yielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcechgrwzaglzogwjvqnc" + "jzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbcsbfvpylgjznsuhxcx" + "oqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnddxntikgoqlidfnmdh" + "xzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnrftzfeyasjpxoevypt" + "pdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtgokxhegoifakimxbba" + "fkeannglvsxprqzfekdinssqymtfexf"); + assert_int_equal(str->len, 1204); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE * 10); + assert_null(b_string_free(str, true)); +} + + +static void +test_string_append(void **state) +{ + b_string_t *str = b_string_new(); + str = b_string_append(str, "guda"); + assert_non_null(str); + assert_string_equal(str->str, "guda"); + assert_int_equal(str->len, 4); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); + str = b_string_new(); + str = b_string_append(str, "guda"); + str = b_string_append(str, "bola"); + assert_non_null(str); + assert_string_equal(str->str, "gudabola"); + assert_int_equal(str->len, 8); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); + str = b_string_new(); + str = b_string_append(str, "guda"); + str = b_string_append(str, + "cwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcw" + "nnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwa" + "xfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevaz" + "dxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcec" + "hgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbc" + "sbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnd" + "dxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnr" + "ftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtg" + "okxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexf"); + str = b_string_append(str, NULL); + str = b_string_append(str, + "cwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcw" + "nnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwa" + "xfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevaz" + "dxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcec" + "hgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbc" + "sbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnd" + "dxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnr" + "ftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtg" + "okxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexf"); + assert_non_null(str); + assert_string_equal(str->str, + "gudacwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjid" + "zkcwnnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtax" + "jiwaxfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqv" + "evazdxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywh" + "qcechgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxj" + "rsbcsbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqd" + "atnddxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvw" + "srnrftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsf" + "nwtgokxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexfcwlwmwxxmvjnwtidm" + "jehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcwnnqhxhneolbwqlctc" + "xmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwaxfhfyzymtffusoqyw" + "aruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevazdxrewtgapkompnvii" + "yielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcechgrwzaglzogwjvqnc" + "jzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbcsbfvpylgjznsuhxcx" + "oqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnddxntikgoqlidfnmdh" + "xzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnrftzfeyasjpxoevypt" + "pdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtgokxhegoifakimxbba" + "fkeannglvsxprqzfekdinssqymtfexf"); + assert_int_equal(str->len, 1204); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE * 10); + assert_null(b_string_free(str, true)); +} + + +static void +test_string_append_c(void **state) +{ + b_string_t *str = b_string_new(); + str = b_string_append_len(str, "guda", 4); + for (int i = 0; i < 600; i++) + str = b_string_append_c(str, 'c'); + assert_non_null(str); + assert_string_equal(str->str, + "gudaccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "cccccccccccccccccccccccccccccccccccccccccccccccccccc"); + assert_int_equal(str->len, 604); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE * 5); + assert_null(b_string_free(str, true)); +} + + +static void +test_string_append_printf(void **state) +{ + b_string_t *str = b_string_new(); + str = b_string_append_printf(str, "guda: %s %d", "bola", 1); + assert_non_null(str); + assert_string_equal(str->str, "guda: bola 1"); + assert_int_equal(str->len, 12); + assert_int_equal(str->allocated_len, B_STRING_CHUNK_SIZE); + assert_null(b_string_free(str, true)); +} + + +static void +test_trie_new(void **state) +{ + b_trie_t *trie = b_trie_new(free); + assert_non_null(trie); + assert_null(trie->root); + assert_true(trie->free_func == free); + b_trie_free(trie); +} + + +static void +test_trie_insert(void **state) +{ + b_trie_t *trie = b_trie_new(free); + + b_trie_insert(trie, "bola", b_strdup("guda")); + assert_true(trie->root->key == 'b'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'o'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'l'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == 'a'); + assert_null(trie->root->child->child->child->data); + assert_true(trie->root->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->child->data, "guda"); + + + b_trie_insert(trie, "chu", b_strdup("nda")); + assert_true(trie->root->key == 'b'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'o'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'l'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == 'a'); + assert_null(trie->root->child->child->child->data); + assert_true(trie->root->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->child->data, "guda"); + + assert_true(trie->root->next->key == 'c'); + assert_null(trie->root->next->data); + assert_true(trie->root->next->child->key == 'h'); + assert_null(trie->root->next->child->data); + assert_true(trie->root->next->child->child->key == 'u'); + assert_null(trie->root->next->child->child->data); + assert_true(trie->root->next->child->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->child->data, "nda"); + + + b_trie_insert(trie, "bote", b_strdup("aba")); + assert_true(trie->root->key == 'b'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'o'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'l'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == 'a'); + assert_null(trie->root->child->child->child->data); + assert_true(trie->root->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->child->data, "guda"); + + assert_true(trie->root->next->key == 'c'); + assert_null(trie->root->next->data); + assert_true(trie->root->next->child->key == 'h'); + assert_null(trie->root->next->child->data); + assert_true(trie->root->next->child->child->key == 'u'); + assert_null(trie->root->next->child->child->data); + assert_true(trie->root->next->child->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->child->data, "nda"); + + assert_true(trie->root->child->child->next->key == 't'); + assert_null(trie->root->child->child->next->data); + assert_true(trie->root->child->child->next->child->key == 'e'); + assert_null(trie->root->child->child->next->child->data); + assert_true(trie->root->child->child->next->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->next->child->child->data, "aba"); + + + b_trie_insert(trie, "bo", b_strdup("haha")); + assert_true(trie->root->key == 'b'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'o'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'l'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == 'a'); + assert_null(trie->root->child->child->child->data); + assert_true(trie->root->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->child->data, "guda"); + + assert_true(trie->root->next->key == 'c'); + assert_null(trie->root->next->data); + assert_true(trie->root->next->child->key == 'h'); + assert_null(trie->root->next->child->data); + assert_true(trie->root->next->child->child->key == 'u'); + assert_null(trie->root->next->child->child->data); + assert_true(trie->root->next->child->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->child->data, "nda"); + + assert_true(trie->root->child->child->next->key == 't'); + assert_null(trie->root->child->child->next->data); + assert_true(trie->root->child->child->next->child->key == 'e'); + assert_null(trie->root->child->child->next->child->data); + assert_true(trie->root->child->child->next->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->next->child->child->data, "aba"); + + assert_true(trie->root->child->child->next->next->key == '\0'); + assert_string_equal(trie->root->child->child->next->next->data, "haha"); + + b_trie_free(trie); + + + trie = b_trie_new(free); + + b_trie_insert(trie, "chu", b_strdup("nda")); + assert_true(trie->root->key == 'c'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'h'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'u'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->data, "nda"); + + + b_trie_insert(trie, "bola", b_strdup("guda")); + assert_true(trie->root->key == 'c'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'h'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'u'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->data, "nda"); + + assert_true(trie->root->next->key == 'b'); + assert_null(trie->root->next->data); + assert_true(trie->root->next->child->key == 'o'); + assert_null(trie->root->next->child->data); + assert_true(trie->root->next->child->child->key == 'l'); + assert_null(trie->root->next->child->child->data); + assert_true(trie->root->next->child->child->child->key == 'a'); + assert_null(trie->root->next->child->child->child->data); + assert_true(trie->root->next->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->child->child->data, "guda"); + + + b_trie_insert(trie, "bote", b_strdup("aba")); + assert_true(trie->root->key == 'c'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'h'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'u'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->data, "nda"); + + assert_true(trie->root->next->key == 'b'); + assert_null(trie->root->next->data); + assert_true(trie->root->next->child->key == 'o'); + assert_null(trie->root->next->child->data); + assert_true(trie->root->next->child->child->key == 'l'); + assert_null(trie->root->next->child->child->data); + assert_true(trie->root->next->child->child->child->key == 'a'); + assert_null(trie->root->next->child->child->child->data); + assert_true(trie->root->next->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->child->child->data, "guda"); + + assert_true(trie->root->next->child->child->next->key == 't'); + assert_null(trie->root->next->child->child->next->data); + assert_true(trie->root->next->child->child->next->child->key == 'e'); + assert_null(trie->root->next->child->child->next->child->data); + assert_true(trie->root->next->child->child->next->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->next->child->child->data, "aba"); + + + b_trie_insert(trie, "bo", b_strdup("haha")); + assert_true(trie->root->key == 'c'); + assert_null(trie->root->data); + assert_true(trie->root->child->key == 'h'); + assert_null(trie->root->child->data); + assert_true(trie->root->child->child->key == 'u'); + assert_null(trie->root->child->child->data); + assert_true(trie->root->child->child->child->key == '\0'); + assert_string_equal(trie->root->child->child->child->data, "nda"); + + assert_true(trie->root->next->key == 'b'); + assert_null(trie->root->next->data); + assert_true(trie->root->next->child->key == 'o'); + assert_null(trie->root->next->child->data); + assert_true(trie->root->next->child->child->key == 'l'); + assert_null(trie->root->next->child->child->data); + assert_true(trie->root->next->child->child->child->key == 'a'); + assert_null(trie->root->next->child->child->child->data); + assert_true(trie->root->next->child->child->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->child->child->data, "guda"); + + assert_true(trie->root->next->child->child->next->key == 't'); + assert_null(trie->root->next->child->child->next->data); + assert_true(trie->root->next->child->child->next->child->key == 'e'); + assert_null(trie->root->next->child->child->next->child->data); + assert_true(trie->root->next->child->child->next->child->child->key == '\0'); + assert_string_equal(trie->root->next->child->child->next->child->child->data, "aba"); + + assert_true(trie->root->next->child->child->next->next->key == '\0'); + assert_string_equal(trie->root->next->child->child->next->next->data, "haha"); + + b_trie_free(trie); +} + + +static void +test_trie_keep_data(void **state) +{ + b_trie_t *trie = b_trie_new(NULL); + + char *t1 = "guda"; + char *t2 = "nda"; + char *t3 = "aba"; + char *t4 = "haha"; + + b_trie_insert(trie, "bola", t1); + b_trie_insert(trie, "chu", t2); + b_trie_insert(trie, "bote", t3); + b_trie_insert(trie, "bo", t4); + + b_trie_free(trie); + + assert_string_equal(t1, "guda"); + assert_string_equal(t2, "nda"); + assert_string_equal(t3, "aba"); + assert_string_equal(t4, "haha"); +} + + +static void +test_trie_lookup(void **state) +{ + b_trie_t *trie = b_trie_new(free); + + b_trie_insert(trie, "bola", b_strdup("guda")); + b_trie_insert(trie, "chu", b_strdup("nda")); + b_trie_insert(trie, "bote", b_strdup("aba")); + b_trie_insert(trie, "bo", b_strdup("haha")); + + assert_string_equal(b_trie_lookup(trie, "bola"), "guda"); + assert_string_equal(b_trie_lookup(trie, "chu"), "nda"); + assert_string_equal(b_trie_lookup(trie, "bote"), "aba"); + assert_string_equal(b_trie_lookup(trie, "bo"), "haha"); + + assert_null(b_trie_lookup(trie, "arcoiro")); + + b_trie_free(trie); + + trie = b_trie_new(free); + + b_trie_insert(trie, "chu", b_strdup("nda")); + b_trie_insert(trie, "bola", b_strdup("guda")); + b_trie_insert(trie, "bote", b_strdup("aba")); + b_trie_insert(trie, "bo", b_strdup("haha")); + b_trie_insert(trie, "copa", b_strdup("bu")); + b_trie_insert(trie, "b", b_strdup("c")); + b_trie_insert(trie, "test", b_strdup("asd")); + + assert_string_equal(b_trie_lookup(trie, "bola"), "guda"); + assert_string_equal(b_trie_lookup(trie, "chu"), "nda"); + assert_string_equal(b_trie_lookup(trie, "bote"), "aba"); + assert_string_equal(b_trie_lookup(trie, "bo"), "haha"); + + assert_null(b_trie_lookup(trie, "arcoiro")); + + b_trie_free(trie); +} + + +static void +test_trie_size(void **state) +{ + b_trie_t *trie = b_trie_new(free); + + b_trie_insert(trie, "bola", b_strdup("guda")); + b_trie_insert(trie, "chu", b_strdup("nda")); + b_trie_insert(trie, "bote", b_strdup("aba")); + b_trie_insert(trie, "bo", b_strdup("haha")); + + assert_int_equal(b_trie_size(trie), 4); + assert_int_equal(b_trie_size(NULL), 0); + + b_trie_free(trie); + + trie = b_trie_new(free); + + b_trie_insert(trie, "chu", b_strdup("nda")); + b_trie_insert(trie, "bola", b_strdup("guda")); + b_trie_insert(trie, "bote", b_strdup("aba")); + b_trie_insert(trie, "bo", b_strdup("haha")); + b_trie_insert(trie, "copa", b_strdup("bu")); + b_trie_insert(trie, "b", b_strdup("c")); + b_trie_insert(trie, "test", b_strdup("asd")); + + assert_int_equal(b_trie_size(trie), 7); + assert_int_equal(b_trie_size(NULL), 0); + + b_trie_free(trie); +} + + +static unsigned int counter; +static char *expected_keys[] = {"chu", "copa", "bola", "bote", "bo", "b", "test"}; +static char *expected_datas[] = {"nda", "bu", "guda", "aba", "haha", "c", "asd"}; + +static void +mock_foreach(const char *key, void *data) +{ + assert_string_equal(key, expected_keys[counter]); + assert_string_equal((char*) data, expected_datas[counter++]); +} + + +static void +test_trie_foreach(void **state) +{ + b_trie_t *trie = b_trie_new(free); + + b_trie_insert(trie, "chu", b_strdup("nda")); + b_trie_insert(trie, "bola", b_strdup("guda")); + b_trie_insert(trie, "bote", b_strdup("aba")); + b_trie_insert(trie, "bo", b_strdup("haha")); + b_trie_insert(trie, "copa", b_strdup("bu")); + b_trie_insert(trie, "b", b_strdup("c")); + b_trie_insert(trie, "test", b_strdup("asd")); + + counter = 0; + b_trie_foreach(trie, mock_foreach); + + b_trie_free(trie); +} + + +int +main(void) +{ + const UnitTest tests[] = { + + // slist + unit_test(test_slist_append), + unit_test(test_slist_free), + unit_test(test_slist_length), + + // strings + unit_test(test_strdup), + unit_test(test_strndup), + unit_test(test_strdup_printf), + unit_test(test_str_starts_with), + unit_test(test_str_ends_with), + unit_test(test_str_strip), + unit_test(test_str_split), + unit_test(test_str_replace), + unit_test(test_strv_join), + unit_test(test_strv_length), + unit_test(test_string_new), + unit_test(test_string_free), + unit_test(test_string_append_len), + unit_test(test_string_append), + unit_test(test_string_append_c), + unit_test(test_string_append_printf), + + // trie + unit_test(test_trie_new), + unit_test(test_trie_insert), + unit_test(test_trie_keep_data), + unit_test(test_trie_lookup), + unit_test(test_trie_size), + unit_test(test_trie_foreach), + }; + return run_tests(tests); +} |