diff options
author | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2016-04-27 01:38:10 +0200 |
---|---|---|
committer | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2016-04-27 02:19:37 +0200 |
commit | 74b2ee22a6b60d53b1241e0c52284b288e561599 (patch) | |
tree | 8d1b197f657af22912f8e6d611c6c9cccd9890d9 | |
parent | 6153580a13e7e7c48e38fa446572c8adcae08084 (diff) | |
download | blogc-74b2ee22a6b60d53b1241e0c52284b288e561599.tar.gz blogc-74b2ee22a6b60d53b1241e0c52284b288e561599.tar.bz2 blogc-74b2ee22a6b60d53b1241e0c52284b288e561599.zip |
moved squareball back to blogc source tree.
i don't have enough time to maintain a separated library at this point,
and worry about soname bump, library stability, etc. all the code is
trivial enough to be copied around, and all the utils are implemented as
single file now, to make it easier to copy.
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | Makefile.am | 43 | ||||
-rw-r--r-- | configure.ac | 24 | ||||
m--------- | squareball | 0 | ||||
-rw-r--r-- | src/utils.c | 612 | ||||
-rw-r--r-- | src/utils.h | 102 | ||||
-rw-r--r-- | tests/check_source_parser.c | 2 | ||||
-rw-r--r-- | tests/check_utils.c | 959 |
8 files changed, 1694 insertions, 51 deletions
diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 061fb99..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "squareball"] - path = squareball - url = https://github.com/rafaelmartins/squareball.git diff --git a/Makefile.am b/Makefile.am index a0559ea..8237508 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,16 +1,11 @@ ## Autotools settings -if INTERNAL_SQUAREBALL -SUBDIRS = squareball -endif - ACLOCAL_AMFLAGS = -I m4 AM_DISTCHECK_CONFIGURE_FLAGS = \ --enable-tests \ --enable-ronn \ --disable-valgrind \ - --with-squareball=internal \ $(NULL) @@ -43,6 +38,7 @@ noinst_HEADERS = \ src/renderer.h \ src/source-parser.h \ src/template-parser.h \ + src/utils.h \ $(NULL) noinst_LTLIBRARIES = \ @@ -69,17 +65,16 @@ libblogc_la_SOURCES = \ src/renderer.c \ src/source-parser.c \ src/template-parser.c \ + src/utils.c \ $(NULL) libblogc_la_CFLAGS = \ $(AM_CFLAGS) \ -I$(top_srcdir)/src \ - $(SQUAREBALL_CFLAGS) \ $(NULL) libblogc_la_LIBADD = \ $(LIBM) \ - $(SQUAREBALL_LIBS) \ $(NULL) @@ -90,12 +85,10 @@ blogc_SOURCES = \ blogc_CFLAGS = \ $(AM_CFLAGS) \ -I$(top_srcdir)/src \ - $(SQUAREBALL_CFLAGS) \ $(NULL) blogc_LDADD = \ libblogc.la \ - $(SQUAREBALL_LIBS) \ $(NULL) @@ -170,6 +163,7 @@ check_PROGRAMS += \ tests/check_renderer \ tests/check_source_parser \ tests/check_template_parser \ + tests/check_utils \ $(NULL) tests_check_error_SOURCES = \ @@ -177,7 +171,6 @@ tests_check_error_SOURCES = \ $(NULL) tests_check_error_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -186,7 +179,6 @@ tests_check_error_LDFLAGS = \ $(NULL) tests_check_error_LDADD = \ - $(SQUAREBALL_LIBS) \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) @@ -196,7 +188,6 @@ tests_check_loader_SOURCES = \ $(NULL) tests_check_loader_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -207,7 +198,6 @@ tests_check_loader_LDFLAGS = \ $(NULL) tests_check_loader_LDADD = \ - $(SQUAREBALL_LIBS) \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) @@ -217,7 +207,6 @@ tests_check_content_parser_SOURCES = \ $(NULL) tests_check_content_parser_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -226,7 +215,6 @@ tests_check_content_parser_LDFLAGS = \ $(NULL) tests_check_content_parser_LDADD = \ - $(SQUAREBALL_LIBS) \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) @@ -236,7 +224,6 @@ tests_check_datetime_parser_SOURCES = \ $(NULL) tests_check_datetime_parser_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -245,7 +232,6 @@ tests_check_datetime_parser_LDFLAGS = \ $(NULL) tests_check_datetime_parser_LDADD = \ - $(SQUAREBALL_LIBS) \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) @@ -255,7 +241,6 @@ tests_check_renderer_SOURCES = \ $(NULL) tests_check_renderer_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -264,7 +249,6 @@ tests_check_renderer_LDFLAGS = \ $(NULL) tests_check_renderer_LDADD = \ - $(SQUAREBALL_LIBS) \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) @@ -274,7 +258,6 @@ tests_check_source_parser_SOURCES = \ $(NULL) tests_check_source_parser_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -283,7 +266,6 @@ tests_check_source_parser_LDFLAGS = \ $(NULL) tests_check_source_parser_LDADD = \ - $(SQUAREBALL_LIBS) \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) @@ -293,7 +275,6 @@ tests_check_template_parser_SOURCES = \ $(NULL) tests_check_template_parser_CFLAGS = \ - $(SQUAREBALL_CFLAGS) \ $(CMOCKA_CFLAGS) \ $(NULL) @@ -302,7 +283,23 @@ tests_check_template_parser_LDFLAGS = \ $(NULL) tests_check_template_parser_LDADD = \ - $(SQUAREBALL_LIBS) \ + $(CMOCKA_LIBS) \ + libblogc.la \ + $(NULL) + +tests_check_utils_SOURCES = \ + tests/check_utils.c \ + $(NULL) + +tests_check_utils_CFLAGS = \ + $(CMOCKA_CFLAGS) \ + $(NULL) + +tests_check_utils_LDFLAGS = \ + -no-install \ + $(NULL) + +tests_check_utils_LDADD = \ $(CMOCKA_LIBS) \ libblogc.la \ $(NULL) diff --git a/configure.ac b/configure.ac index 0bc1e19..1e7366e 100644 --- a/configure.ac +++ b/configure.ac @@ -123,29 +123,6 @@ AC_CHECK_HEADERS([sys/types.h sys/stat.h time.h]) LT_LIB_M -AC_ARG_WITH([squareball], [AS_HELP_STRING([--with-squareball=@<:@internal/system@:>@], - [whether to use library squareball from system [default=internal]])]) -AS_IF([test "x$with_squareball" = "xsystem"], [ - SQUAREBALL="system" - PKG_CHECK_MODULES([SQUAREBALL], [squareball >= 0.2.0], , [ - AC_MSG_ERROR([library squareball requested from system but not found or not new enough]) - ]) -], [ - SQUAREBALL="internal" - SQUAREBALL_CFLAGS='-I$(top_srcdir)/squareball/src' - SQUAREBALL_LIBS='$(top_builddir)/squareball/libsquareball.la' - AC_SUBST(SQUAREBALL_LIBS) - AC_SUBST(SQUAREBALL_CFLAGS) - ac_configure_args_pre="$ac_configure_args" - ac_configure_args_post="$ac_configure_args --enable-bundleme" - ac_configure_args="$ac_configure_args_post" - AC_CONFIG_COMMANDS_PRE([ac_configure_args="$ac_configure_args_pre"]) - AC_CONFIG_COMMANDS_POST([ac_configure_args="$ac_configure_args_post"]) - AC_CONFIG_SUBDIRS([squareball]) - ac_configure_args="$ac_configure_args_pre" -]) -AM_CONDITIONAL(INTERNAL_SQUAREBALL, [test "x$with_squareball" != "xsystem"]) - AC_CONFIG_FILES([ Makefile blogc.spec @@ -164,7 +141,6 @@ AS_ECHO(" cflags: ${CFLAGS} ldflags: ${LDFLAGS} - squareball: ${SQUAREBALL} tests: ${TESTS} ronn: ${RONN} diff --git a/squareball b/squareball deleted file mode 160000 -Subproject e2639b044e450ed54cf6e768ed2eb8b88e5c055 diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..855b503 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,612 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#define SB_STRING_CHUNK_SIZE 128 + +#include <ctype.h> +#include <string.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> + +#include "utils.h" + + +void* +sb_malloc(size_t size) +{ + // simple things simple! + void *rv = malloc(size); + if (rv == NULL) { + fprintf(stderr, "fatal: Failed to allocate memory!\n"); + abort(); + } + return rv; +} + + +void* +sb_realloc(void *ptr, size_t size) +{ + // simple things even simpler :P + void *rv = realloc(ptr, size); + if (rv == NULL && size != 0) { + fprintf(stderr, "fatal: Failed to reallocate memory!\n"); + free(ptr); + abort(); + } + return rv; +} + + +sb_slist_t* +sb_slist_append(sb_slist_t *l, void *data) +{ + sb_slist_t *node = sb_malloc(sizeof(sb_slist_t)); + node->data = data; + node->next = NULL; + if (l == NULL) { + l = node; + } + else { + sb_slist_t *tmp; + for (tmp = l; tmp->next != NULL; tmp = tmp->next); + tmp->next = node; + } + return l; +} + + +sb_slist_t* +sb_slist_prepend(sb_slist_t *l, void *data) +{ + sb_slist_t *node = sb_malloc(sizeof(sb_slist_t)); + node->data = data; + node->next = l; + l = node; + return l; +} + + +void +sb_slist_free_full(sb_slist_t *l, sb_free_func_t free_func) +{ + while (l != NULL) { + sb_slist_t *tmp = l->next; + if ((free_func != NULL) && (l->data != NULL)) + free_func(l->data); + free(l); + l = tmp; + } +} + + +void +sb_slist_free(sb_slist_t *l) +{ + sb_slist_free_full(l, NULL); +} + + +size_t +sb_slist_length(sb_slist_t *l) +{ + if (l == NULL) + return 0; + size_t i; + sb_slist_t *tmp; + for (tmp = l, i = 0; tmp != NULL; tmp = tmp->next, i++); + return i; +} + + +char* +sb_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* +sb_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* +sb_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) { + free(tmp); + return NULL; + } + return tmp; +} + + +char* +sb_strdup_printf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + char *tmp = sb_strdup_vprintf(format, ap); + va_end(ap); + return tmp; +} + + +bool +sb_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 +sb_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* +sb_str_lstrip(char *str) +{ + if (str == NULL) + return NULL; + int i; + size_t str_len = strlen(str); + for (i = 0; i < str_len; i++) { + if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') && + (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') && + (str[i] != '\v')) + { + str += i; + break; + } + if (i == str_len - 1) { + str += str_len; + break; + } + } + return str; +} + + +char* +sb_str_rstrip(char *str) +{ + if (str == NULL) + return NULL; + int i; + size_t str_len = strlen(str); + for (i = str_len - 1; i >= 0; i--) { + if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') && + (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') && + (str[i] != '\v')) + { + str[i + 1] = '\0'; + break; + } + if (i == 0) { + str[0] = '\0'; + break; + } + } + return str; +} + + +char* +sb_str_strip(char *str) +{ + return sb_str_lstrip(sb_str_rstrip(str)); +} + + +char** +sb_str_split(const char *str, char c, unsigned int max_pieces) +{ + if (str == NULL) + return NULL; + char **rv = sb_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 = sb_realloc(rv, (count + 1) * sizeof(char*)); + rv[count] = sb_malloc(i - start + 1); + memcpy(rv[count], str + start, i - start); + rv[count++][i - start] = '\0'; + start = i + 1; + } + } + rv = sb_realloc(rv, (count + 1) * sizeof(char*)); + rv[count] = NULL; + return rv; +} + + +char* +sb_str_replace(const char *str, const char search, const char *replace) +{ + char **pieces = sb_str_split(str, search, 0); + if (pieces == NULL) + return NULL; + char* rv = sb_strv_join(pieces, replace); + sb_strv_free(pieces); + if (rv == NULL) + return sb_strdup(str); + return rv; +} + + +void +sb_strv_free(char **strv) +{ + if (strv == NULL) + return; + for (size_t i = 0; strv[i] != NULL; i++) + free(strv[i]); + free(strv); +} + + +char* +sb_strv_join(char **strv, const char *separator) +{ + if (strv == NULL || separator == NULL) + return NULL; + sb_string_t *str = sb_string_new(); + for (size_t i = 0; strv[i] != NULL; i++) { + str = sb_string_append(str, strv[i]); + if (strv[i + 1] != NULL) + str = sb_string_append(str, separator); + } + return sb_string_free(str, false); +} + + +size_t +sb_strv_length(char **strv) +{ + if (strv == NULL) + return 0; + size_t i; + for (i = 0; strv[i] != NULL; i++); + return i; +} + + +sb_string_t* +sb_string_new(void) +{ + sb_string_t* rv = sb_malloc(sizeof(sb_string_t)); + rv->str = NULL; + rv->len = 0; + rv->allocated_len = 0; + + // initialize with empty string + rv = sb_string_append(rv, ""); + + return rv; +} + + +char* +sb_string_free(sb_string_t *str, bool free_str) +{ + if (str == NULL) + return NULL; + char *rv = NULL; + if (free_str) + free(str->str); + else + rv = str->str; + free(str); + return rv; +} + + +sb_string_t* +sb_string_dup(sb_string_t *str) +{ + if (str == NULL) + return NULL; + sb_string_t* new = sb_string_new(); + return sb_string_append_len(new, str->str, str->len); +} + + +sb_string_t* +sb_string_append_len(sb_string_t *str, const char *suffix, size_t len) +{ + if (str == NULL) + return NULL; + 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) / SB_STRING_CHUNK_SIZE) + 1) * SB_STRING_CHUNK_SIZE; + str->str = sb_realloc(str->str, str->allocated_len); + } + memcpy(str->str + old_len, suffix, len); + str->str[str->len] = '\0'; + return str; +} + + +sb_string_t* +sb_string_append(sb_string_t *str, const char *suffix) +{ + if (str == NULL) + return NULL; + const char *my_suffix = suffix == NULL ? "" : suffix; + return sb_string_append_len(str, my_suffix, strlen(my_suffix)); +} + + +sb_string_t* +sb_string_append_c(sb_string_t *str, char c) +{ + if (str == NULL) + return NULL; + size_t old_len = str->len; + str->len += 1; + if (str->len + 1 > str->allocated_len) { + str->allocated_len = (((str->len + 1) / SB_STRING_CHUNK_SIZE) + 1) * SB_STRING_CHUNK_SIZE; + str->str = sb_realloc(str->str, str->allocated_len); + } + str->str[old_len] = c; + str->str[str->len] = '\0'; + return str; +} + + +sb_string_t* +sb_string_append_printf(sb_string_t *str, const char *format, ...) +{ + if (str == NULL) + return NULL; + va_list ap; + va_start(ap, format); + char *tmp = sb_strdup_vprintf(format, ap); + va_end(ap); + str = sb_string_append(str, tmp); + free(tmp); + return str; +} + + +sb_trie_t* +sb_trie_new(sb_free_func_t free_func) +{ + sb_trie_t *trie = sb_malloc(sizeof(sb_trie_t)); + trie->root = NULL; + trie->free_func = free_func; + return trie; +} + + +static void +sb_trie_free_node(sb_trie_t *trie, sb_trie_node_t *node) +{ + if (trie == NULL || node == NULL) + return; + if (node->data != NULL && trie->free_func != NULL) + trie->free_func(node->data); + sb_trie_free_node(trie, node->next); + sb_trie_free_node(trie, node->child); + free(node); +} + + +void +sb_trie_free(sb_trie_t *trie) +{ + if (trie == NULL) + return; + sb_trie_free_node(trie, trie->root); + free(trie); +} + + +void +sb_trie_insert(sb_trie_t *trie, const char *key, void *data) +{ + if (trie == NULL || key == NULL || data == NULL) + return; + + sb_trie_node_t *parent = NULL; + sb_trie_node_t *previous; + sb_trie_node_t *current; + sb_trie_node_t *tmp; + + while (1) { + + if (trie->root == NULL || (parent != NULL && parent->child == NULL)) { + current = sb_malloc(sizeof(sb_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 = sb_malloc(sizeof(sb_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + previous->next = current; + parent = current; + +clean: + if (*key == '\0') { + if (parent->data != NULL && trie->free_func != NULL) + trie->free_func(parent->data); + parent->data = data; + break; + } + key++; + } +} + + +void* +sb_trie_lookup(sb_trie_t *trie, const char *key) +{ + if (trie == NULL || trie->root == NULL || key == NULL) + return NULL; + + sb_trie_node_t *parent = trie->root; + sb_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 +sb_trie_size_node(sb_trie_node_t *node, size_t *count) +{ + if (node == NULL || count == NULL) + return; + + if (node->key == '\0') + (*count)++; + + sb_trie_size_node(node->next, count); + sb_trie_size_node(node->child, count); +} + + +size_t +sb_trie_size(sb_trie_t *trie) +{ + if (trie == NULL) + return 0; + + size_t count = 0; + sb_trie_size_node(trie->root, &count); + return count; +} + + +static void +sb_trie_foreach_node(sb_trie_node_t *node, sb_string_t *str, + sb_trie_foreach_func_t func, void *user_data) +{ + if (node == NULL || str == NULL || func == NULL) + return; + + if (node->key == '\0') { + char *tmp = sb_string_free(str, false); + func(tmp, node->data, user_data); + free(tmp); + } + + if (node->child != NULL) { + sb_string_t *child = sb_string_dup(str); + child = sb_string_append_c(child, node->key); + sb_trie_foreach_node(node->child, child, func, user_data); + } + + if (node->next != NULL) + sb_trie_foreach_node(node->next, str, func, user_data); + + if (node->child != NULL && node->next == NULL) + sb_string_free(str, true); +} + + +void +sb_trie_foreach(sb_trie_t *trie, sb_trie_foreach_func_t func, + void *user_data) +{ + if (trie == NULL || trie->root == NULL || func == NULL) + return; + + sb_string_t *str = sb_string_new(); + sb_trie_foreach_node(trie->root, str, func, user_data); +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..411295a --- /dev/null +++ b/src/utils.h @@ -0,0 +1,102 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _UTILS_H +#define _UTILS_H + +#include <stddef.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdarg.h> +#include <stdlib.h> + + +// memory + +typedef void (*sb_free_func_t) (void *ptr); + +void* sb_malloc(size_t size); +void* sb_realloc(void *ptr, size_t size); + + +// slist + +typedef struct _sb_slist_t { + struct _sb_slist_t *next; + void *data; +} sb_slist_t; + +sb_slist_t* sb_slist_append(sb_slist_t *l, void *data); +sb_slist_t* sb_slist_prepend(sb_slist_t *l, void *data); +void sb_slist_free(sb_slist_t *l); +void sb_slist_free_full(sb_slist_t *l, sb_free_func_t free_func); +size_t sb_slist_length(sb_slist_t *l); + + +// strfuncs + +char* sb_strdup(const char *s); +char* sb_strndup(const char *s, size_t n); +char* sb_strdup_vprintf(const char *format, va_list ap); +char* sb_strdup_printf(const char *format, ...); +bool sb_str_starts_with(const char *str, const char *prefix); +bool sb_str_ends_with(const char *str, const char *suffix); +char* sb_str_lstrip(char *str); +char* sb_str_rstrip(char *str); +char* sb_str_strip(char *str); +char** sb_str_split(const char *str, char c, unsigned int max_pieces); +char* sb_str_replace(const char *str, const char search, const char *replace); +void sb_strv_free(char **strv); +char* sb_strv_join(char **strv, const char *separator); +size_t sb_strv_length(char **strv); + + +// string + +typedef struct { + char *str; + size_t len; + size_t allocated_len; +} sb_string_t; + +sb_string_t* sb_string_new(void); +char* sb_string_free(sb_string_t *str, bool free_str); +sb_string_t* sb_string_dup(sb_string_t *str); +sb_string_t* sb_string_append_len(sb_string_t *str, const char *suffix, size_t len); +sb_string_t* sb_string_append(sb_string_t *str, const char *suffix); +sb_string_t* sb_string_append_c(sb_string_t *str, char c); +sb_string_t* sb_string_append_printf(sb_string_t *str, const char *format, ...); + + +// trie + +typedef struct _sb_trie_node_t { + char key; + void *data; + struct _sb_trie_node_t *next, *child; +} sb_trie_node_t; + +struct _sb_trie_t { + sb_trie_node_t *root; + sb_free_func_t free_func; +}; + +typedef struct _sb_trie_t sb_trie_t; + +typedef void (*sb_trie_foreach_func_t)(const char *key, void *data, + void *user_data); + +sb_trie_t* sb_trie_new(sb_free_func_t free_func); +void sb_trie_free(sb_trie_t *trie); +void sb_trie_insert(sb_trie_t *trie, const char *key, void *data); +void* sb_trie_lookup(sb_trie_t *trie, const char *key); +size_t sb_trie_size(sb_trie_t *trie); +void sb_trie_foreach(sb_trie_t *trie, sb_trie_foreach_func_t func, + void *user_data); + +#endif /* _UTILS_H */ diff --git a/tests/check_source_parser.c b/tests/check_source_parser.c index 0f891dd..477399c 100644 --- a/tests/check_source_parser.c +++ b/tests/check_source_parser.c @@ -173,7 +173,7 @@ test_source_parse_with_description(void **state) "# This is a test\n" "\n" "bola\n"; - sb_error_t *err = NULL; + blogc_error_t *err = NULL; sb_trie_t *source = blogc_source_parse(a, strlen(a), &err); assert_null(err); assert_non_null(source); diff --git a/tests/check_utils.c b/tests/check_utils.c new file mode 100644 index 0000000..6a6ceca --- /dev/null +++ b/tests/check_utils.c @@ -0,0 +1,959 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <stdlib.h> + +#include "../src/utils.h" + +#define SB_STRING_CHUNK_SIZE 128 + + +static void +test_slist_append(void **state) +{ + sb_slist_t *l = NULL; + l = sb_slist_append(l, (void*) sb_strdup("bola")); + assert_non_null(l); + assert_string_equal(l->data, "bola"); + assert_null(l->next); + l = sb_slist_append(l, (void*) sb_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); + sb_slist_free_full(l, free); +} + + +static void +test_slist_prepend(void **state) +{ + sb_slist_t *l = NULL; + l = sb_slist_prepend(l, (void*) sb_strdup("bola")); + assert_non_null(l); + assert_string_equal(l->data, "bola"); + assert_null(l->next); + l = sb_slist_prepend(l, (void*) sb_strdup("guda")); + assert_non_null(l); + assert_string_equal(l->data, "guda"); + assert_non_null(l->next); + assert_string_equal(l->next->data, "bola"); + assert_null(l->next->next); + sb_slist_free_full(l, free); +} + + +static void +test_slist_free(void **state) +{ + sb_slist_t *l = NULL; + char *t1 = sb_strdup("bola"); + char *t2 = sb_strdup("guda"); + char *t3 = sb_strdup("chunda"); + l = sb_slist_append(l, (void*) t1); + l = sb_slist_append(l, (void*) t2); + l = sb_slist_append(l, (void*) t3); + sb_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) +{ + sb_slist_t *l = NULL; + l = sb_slist_append(l, (void*) sb_strdup("bola")); + l = sb_slist_append(l, (void*) sb_strdup("guda")); + l = sb_slist_append(l, (void*) sb_strdup("chunda")); + assert_int_equal(sb_slist_length(l), 3); + sb_slist_free_full(l, free); + assert_int_equal(sb_slist_length(NULL), 0); +} + + +static void +test_strdup(void **state) +{ + char *str = sb_strdup("bola"); + assert_string_equal(str, "bola"); + free(str); + str = sb_strdup(NULL); + assert_null(str); +} + + +static void +test_strndup(void **state) +{ + char *str = sb_strndup("bolaguda", 4); + assert_string_equal(str, "bola"); + free(str); + str = sb_strndup("bolaguda", 30); + assert_string_equal(str, "bolaguda"); + free(str); + str = sb_strndup("bolaguda", 8); + assert_string_equal(str, "bolaguda"); + free(str); + str = sb_strdup(NULL); + assert_null(str); +} + + +static void +test_strdup_printf(void **state) +{ + char *str = sb_strdup_printf("bola"); + assert_string_equal(str, "bola"); + free(str); + str = sb_strdup_printf("bola, %s", "guda"); + assert_string_equal(str, "bola, guda"); + free(str); +} + + +static void +test_str_starts_with(void **state) +{ + assert_true(sb_str_starts_with("bolaguda", "bola")); + assert_true(sb_str_starts_with("bola", "bola")); + assert_false(sb_str_starts_with("gudabola", "bola")); + assert_false(sb_str_starts_with("guda", "bola")); + assert_false(sb_str_starts_with("bola", "bolaguda")); +} + + +static void +test_str_ends_with(void **state) +{ + assert_true(sb_str_ends_with("bolaguda", "guda")); + assert_true(sb_str_ends_with("bola", "bola")); + assert_false(sb_str_ends_with("gudabola", "guda")); + assert_false(sb_str_ends_with("guda", "bola")); + assert_false(sb_str_ends_with("bola", "gudabola")); +} + + +static void +test_str_lstrip(void **state) +{ + char *str = sb_strdup(" \tbola\n \t"); + assert_string_equal(sb_str_lstrip(str), "bola\n \t"); + free(str); + str = sb_strdup("guda"); + assert_string_equal(sb_str_lstrip(str), "guda"); + free(str); + str = sb_strdup("\n"); + assert_string_equal(sb_str_lstrip(str), ""); + free(str); + str = sb_strdup("\t \n"); + assert_string_equal(sb_str_lstrip(str), ""); + free(str); + str = sb_strdup(""); + assert_string_equal(sb_str_lstrip(str), ""); + free(str); + assert_null(sb_str_lstrip(NULL)); +} + + +static void +test_str_rstrip(void **state) +{ + char *str = sb_strdup(" \tbola\n \t"); + assert_string_equal(sb_str_rstrip(str), " \tbola"); + free(str); + str = sb_strdup("guda"); + assert_string_equal(sb_str_rstrip(str), "guda"); + free(str); + str = sb_strdup("\n"); + assert_string_equal(sb_str_rstrip(str), ""); + free(str); + str = sb_strdup("\t \n"); + assert_string_equal(sb_str_rstrip(str), ""); + free(str); + str = sb_strdup(""); + assert_string_equal(sb_str_rstrip(str), ""); + free(str); + assert_null(sb_str_rstrip(NULL)); +} + + +static void +test_str_strip(void **state) +{ + char *str = sb_strdup(" \tbola\n \t"); + assert_string_equal(sb_str_strip(str), "bola"); + free(str); + str = sb_strdup("guda"); + assert_string_equal(sb_str_strip(str), "guda"); + free(str); + str = sb_strdup("\n"); + assert_string_equal(sb_str_strip(str), ""); + free(str); + str = sb_strdup("\t \n"); + assert_string_equal(sb_str_strip(str), ""); + free(str); + str = sb_strdup(""); + assert_string_equal(sb_str_strip(str), ""); + free(str); + assert_null(sb_str_strip(NULL)); +} + + +static void +test_str_split(void **state) +{ + char **strv = sb_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]); + sb_strv_free(strv); + strv = sb_str_split("bola:guda:chunda", ':', 2); + assert_string_equal(strv[0], "bola"); + assert_string_equal(strv[1], "guda:chunda"); + assert_null(strv[2]); + sb_strv_free(strv); + strv = sb_str_split("bola:guda:chunda", ':', 1); + assert_string_equal(strv[0], "bola:guda:chunda"); + assert_null(strv[1]); + sb_strv_free(strv); + strv = sb_str_split("", ':', 1); + assert_null(strv[0]); + sb_strv_free(strv); + assert_null(sb_str_split(NULL, ':', 0)); +} + + +static void +test_str_replace(void **state) +{ + char *str = sb_str_replace("bolao", 'o', "zaz"); + assert_string_equal(str, "bzazlazaz"); + free(str); + str = sb_str_replace("bolao", 'b', "zaz"); + assert_string_equal(str, "zazolao"); + free(str); + str = sb_str_replace("bolao", 'b', NULL); + assert_string_equal(str, "bolao"); + free(str); + assert_null(sb_str_replace(NULL, 'b', "zaz")); +} + + +static void +test_strv_join(void **state) +{ + char *pieces[] = {"guda","bola", "chunda", NULL}; + char *str = sb_strv_join(pieces, ":"); + assert_string_equal(str, "guda:bola:chunda"); + free(str); + char *pieces2[] = {NULL}; + str = sb_strv_join(pieces2, ":"); + assert_string_equal(str, ""); + free(str); + assert_null(sb_strv_join(pieces, NULL)); + assert_null(sb_strv_join(NULL, ":")); + assert_null(sb_strv_join(NULL, NULL)); +} + + +static void +test_strv_length(void **state) +{ + char *pieces[] = {"guda","bola", "chunda", NULL}; + assert_int_equal(sb_strv_length(pieces), 3); + char *pieces2[] = {NULL}; + assert_int_equal(sb_strv_length(pieces2), 0); + assert_int_equal(sb_strv_length(NULL), 0); +} + + +static void +test_string_new(void **state) +{ + sb_string_t *str = sb_string_new(); + assert_non_null(str); + assert_string_equal(str->str, ""); + assert_int_equal(str->len, 0); + assert_int_equal(str->allocated_len, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); +} + + +static void +test_string_free(void **state) +{ + sb_string_t *str = sb_string_new(); + free(str->str); + str->str = sb_strdup("bola"); + str->len = 4; + str->allocated_len = SB_STRING_CHUNK_SIZE; + char *tmp = sb_string_free(str, false); + assert_string_equal(tmp, "bola"); + free(tmp); + assert_null(sb_string_free(NULL, false)); +} + + +static void +test_string_dup(void **state) +{ + sb_string_t *str = sb_string_new(); + free(str->str); + str->str = sb_strdup("bola"); + str->len = 4; + str->allocated_len = SB_STRING_CHUNK_SIZE; + sb_string_t *new = sb_string_dup(str); + assert_non_null(new); + assert_string_equal(new->str, "bola"); + assert_int_equal(new->len, 4); + assert_int_equal(new->allocated_len, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(new, true)); + assert_null(sb_string_free(str, true)); + assert_null(sb_string_dup(NULL)); +} + + +static void +test_string_append_len(void **state) +{ + sb_string_t *str = sb_string_new(); + str = sb_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, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append_len(str, "guda", 4); + str = sb_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, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append_len(str, "guda", 3); + str = sb_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, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append_len(str, "guda", 4); + str = sb_string_append_len(str, + "cwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcw" + "nnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwa" + "xfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevaz" + "dxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcec" + "hgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbc" + "sbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnd" + "dxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnr" + "ftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtg" + "okxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexf", 600); + str = sb_string_append_len(str, NULL, 0); + str = sb_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, SB_STRING_CHUNK_SIZE * 10); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append_len(str, NULL, 0); + assert_non_null(str); + assert_string_equal(str->str, ""); + assert_int_equal(str->len, 0); + assert_int_equal(str->allocated_len, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + assert_null(sb_string_append_len(NULL, "foo", 3)); +} + + +static void +test_string_append(void **state) +{ + sb_string_t *str = sb_string_new(); + str = sb_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, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append(str, "guda"); + str = sb_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, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append(str, "guda"); + str = sb_string_append(str, + "cwlwmwxxmvjnwtidmjehzdeexbxjnjowruxjrqpgpfhmvwgqeacdjissntmbtsjidzkcw" + "nnqhxhneolbwqlctcxmrsutolrjikpavxombpfpjyaqltgvzrjidotalcuwrwxtaxjiwa" + "xfhfyzymtffusoqywaruxpybwggukltspqqmghzpqstvcvlqbkhquihzndnrvkaqvevaz" + "dxrewtgapkompnviiyielanoyowgqhssntyvcvqqtfjmkphywbkvzfyttaalttywhqcec" + "hgrwzaglzogwjvqncjzodaqsblcbpcdpxmrtctzginvtkckhqvdplgjvbzrnarcxjrsbc" + "sbfvpylgjznsuhxcxoqbpxowmsrgwimxjgyzwwmryqvstwzkglgeezelvpvkwefqdatnd" + "dxntikgoqlidfnmdhxzevqzlzubvyleeksdirmmttqthhkvfjggznpmarcamacpvwsrnr" + "ftzfeyasjpxoevyptpdnqokswiondusnuymqwaryrmdgscbnuilxtypuynckancsfnwtg" + "okxhegoifakimxbbafkeannglvsxprqzfekdinssqymtfexf"); + str = sb_string_append(str, NULL); + str = sb_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, SB_STRING_CHUNK_SIZE * 10); + assert_null(sb_string_free(str, true)); + str = sb_string_new(); + str = sb_string_append(str, NULL); + assert_non_null(str); + assert_string_equal(str->str, ""); + assert_int_equal(str->len, 0); + assert_int_equal(str->allocated_len, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + assert_null(sb_string_append(NULL, "asd")); + assert_null(sb_string_append(NULL, NULL)); +} + + +static void +test_string_append_c(void **state) +{ + sb_string_t *str = sb_string_new(); + str = sb_string_append_len(str, "guda", 4); + for (int i = 0; i < 600; i++) + str = sb_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, SB_STRING_CHUNK_SIZE * 5); + assert_null(sb_string_free(str, true)); + assert_null(sb_string_append_c(NULL, 0)); +} + + +static void +test_string_append_printf(void **state) +{ + sb_string_t *str = sb_string_new(); + str = sb_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, SB_STRING_CHUNK_SIZE); + assert_null(sb_string_free(str, true)); + assert_null(sb_string_append_printf(NULL, "asd")); +} + + +static void +test_trie_new(void **state) +{ + sb_trie_t *trie = sb_trie_new(free); + assert_non_null(trie); + assert_null(trie->root); + assert_true(trie->free_func == free); + sb_trie_free(trie); +} + + +static void +test_trie_insert(void **state) +{ + sb_trie_t *trie = sb_trie_new(free); + + sb_trie_insert(trie, "bola", sb_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"); + + + sb_trie_insert(trie, "chu", sb_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"); + + + sb_trie_insert(trie, "bote", sb_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"); + + + sb_trie_insert(trie, "bo", sb_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"); + + sb_trie_free(trie); + + + trie = sb_trie_new(free); + + sb_trie_insert(trie, "chu", sb_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"); + + + sb_trie_insert(trie, "bola", sb_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"); + + + sb_trie_insert(trie, "bote", sb_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"); + + + sb_trie_insert(trie, "bo", sb_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"); + + sb_trie_free(trie); +} + + +static void +test_trie_insert_duplicated(void **state) +{ + sb_trie_t *trie = sb_trie_new(free); + + sb_trie_insert(trie, "bola", sb_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"); + + sb_trie_insert(trie, "bola", sb_strdup("asdf")); + 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, "asdf"); + + sb_trie_free(trie); + + trie = NULL; + sb_trie_insert(trie, "bola", NULL); + assert_null(trie); +} + + +static void +test_trie_keep_data(void **state) +{ + sb_trie_t *trie = sb_trie_new(NULL); + + char *t1 = "guda"; + char *t2 = "nda"; + char *t3 = "aba"; + char *t4 = "haha"; + + sb_trie_insert(trie, "bola", t1); + sb_trie_insert(trie, "chu", t2); + sb_trie_insert(trie, "bote", t3); + sb_trie_insert(trie, "bo", t4); + + sb_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) +{ + sb_trie_t *trie = sb_trie_new(free); + + sb_trie_insert(trie, "bola", sb_strdup("guda")); + sb_trie_insert(trie, "chu", sb_strdup("nda")); + sb_trie_insert(trie, "bote", sb_strdup("aba")); + sb_trie_insert(trie, "bo", sb_strdup("haha")); + + assert_string_equal(sb_trie_lookup(trie, "bola"), "guda"); + assert_string_equal(sb_trie_lookup(trie, "chu"), "nda"); + assert_string_equal(sb_trie_lookup(trie, "bote"), "aba"); + assert_string_equal(sb_trie_lookup(trie, "bo"), "haha"); + + assert_null(sb_trie_lookup(trie, "arcoiro")); + + sb_trie_free(trie); + + trie = sb_trie_new(free); + + sb_trie_insert(trie, "chu", sb_strdup("nda")); + sb_trie_insert(trie, "bola", sb_strdup("guda")); + sb_trie_insert(trie, "bote", sb_strdup("aba")); + sb_trie_insert(trie, "bo", sb_strdup("haha")); + sb_trie_insert(trie, "copa", sb_strdup("bu")); + sb_trie_insert(trie, "b", sb_strdup("c")); + sb_trie_insert(trie, "test", sb_strdup("asd")); + + assert_string_equal(sb_trie_lookup(trie, "bola"), "guda"); + assert_string_equal(sb_trie_lookup(trie, "chu"), "nda"); + assert_string_equal(sb_trie_lookup(trie, "bote"), "aba"); + assert_string_equal(sb_trie_lookup(trie, "bo"), "haha"); + + assert_null(sb_trie_lookup(trie, "arcoiro")); + + sb_trie_free(trie); + + assert_null(sb_trie_lookup(NULL, "bola")); +} + + +static void +test_trie_size(void **state) +{ + sb_trie_t *trie = sb_trie_new(free); + + sb_trie_insert(trie, "bola", sb_strdup("guda")); + sb_trie_insert(trie, "chu", sb_strdup("nda")); + sb_trie_insert(trie, "bote", sb_strdup("aba")); + sb_trie_insert(trie, "bo", sb_strdup("haha")); + + assert_int_equal(sb_trie_size(trie), 4); + assert_int_equal(sb_trie_size(NULL), 0); + + sb_trie_free(trie); + + trie = sb_trie_new(free); + + sb_trie_insert(trie, "chu", sb_strdup("nda")); + sb_trie_insert(trie, "bola", sb_strdup("guda")); + sb_trie_insert(trie, "bote", sb_strdup("aba")); + sb_trie_insert(trie, "bo", sb_strdup("haha")); + sb_trie_insert(trie, "copa", sb_strdup("bu")); + sb_trie_insert(trie, "b", sb_strdup("c")); + sb_trie_insert(trie, "test", sb_strdup("asd")); + + assert_int_equal(sb_trie_size(trie), 7); + assert_int_equal(sb_trie_size(NULL), 0); + + sb_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, void *user_data) +{ + assert_string_equal(user_data, "foo"); + assert_string_equal(key, expected_keys[counter]); + assert_string_equal((char*) data, expected_datas[counter++]); +} + + +static void +test_trie_foreach(void **state) +{ + sb_trie_t *trie = sb_trie_new(free); + + sb_trie_insert(trie, "chu", sb_strdup("nda")); + sb_trie_insert(trie, "bola", sb_strdup("guda")); + sb_trie_insert(trie, "bote", sb_strdup("aba")); + sb_trie_insert(trie, "bo", sb_strdup("haha")); + sb_trie_insert(trie, "copa", sb_strdup("bu")); + sb_trie_insert(trie, "b", sb_strdup("c")); + sb_trie_insert(trie, "test", sb_strdup("asd")); + + counter = 0; + sb_trie_foreach(trie, mock_foreach, "foo"); + sb_trie_foreach(NULL, mock_foreach, "foo"); + sb_trie_foreach(trie, NULL, "foo"); + sb_trie_foreach(NULL, NULL, "foo"); + + sb_trie_free(trie); +} + + +int +main(void) +{ + const UnitTest tests[] = { + + // slist + unit_test(test_slist_append), + unit_test(test_slist_prepend), + unit_test(test_slist_free), + unit_test(test_slist_length), + + // strfuncs + 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_lstrip), + unit_test(test_str_rstrip), + 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), + + // string + unit_test(test_string_new), + unit_test(test_string_free), + unit_test(test_string_dup), + 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_insert_duplicated), + 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); +} |