diff options
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/mem.c | 42 | ||||
| -rw-r--r-- | src/utils/slist.c | 68 | ||||
| -rw-r--r-- | src/utils/strings.c | 283 | ||||
| -rw-r--r-- | src/utils/trie.c | 199 | ||||
| -rw-r--r-- | src/utils/utils.h | 77 | 
5 files changed, 669 insertions, 0 deletions
| diff --git a/src/utils/mem.c b/src/utils/mem.c new file mode 100644 index 0000000..7c5e0a2 --- /dev/null +++ b/src/utils/mem.c @@ -0,0 +1,42 @@ +/* + * 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 LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <stdio.h> +#include "utils.h" + + +void* +b_malloc(size_t size) +{ +    // simple things simple! +    void *rv = malloc(size); +    if (rv == NULL) { +        fprintf(stderr, "fatal error: Failed to allocate memory!\n"); +        exit(1); +    } +    return rv; +} + + +void* +b_realloc(void *ptr, size_t size) +{ +    // simple things even simpler :P +    void *rv = realloc(ptr, size); +    if (rv == NULL && size != 0) { +        fprintf(stderr, "fatal error: Failed to reallocate memory!\n"); +        free(ptr); +        exit(1); +    } +    return rv; +} diff --git a/src/utils/slist.c b/src/utils/slist.c new file mode 100644 index 0000000..3d9b892 --- /dev/null +++ b/src/utils/slist.c @@ -0,0 +1,68 @@ +/* + * 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 LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#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, b_free_func_t free_func) +{ +    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..40174a1 --- /dev/null +++ b/src/utils/strings.c @@ -0,0 +1,283 @@ +/* + * 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 LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#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) { +        free(tmp); +        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 = b_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 = b_realloc(rv, (count + 1) * sizeof(char*)); +            rv[count] = b_malloc(i - start + 1); +            memcpy(rv[count], str + start, i - start); +            rv[count++][i - start] = '\0'; +            start = i + 1; +        } +    } +    rv = b_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 = b_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 = b_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 = b_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..72a62f6 --- /dev/null +++ b/src/utils/trie.c @@ -0,0 +1,199 @@ +/* + * 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 LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdlib.h> +#include "utils.h" + + +b_trie_t* +b_trie_new(b_free_func_t free_func) +{ +    b_trie_t *trie = b_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) +{ +    if (trie == NULL) +        return; +    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 = b_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 = b_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') { +            if (parent->data != NULL && trie->free_func != NULL) +                trie->free_func(parent->data); +            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..5a1505b --- /dev/null +++ b/src/utils/utils.h @@ -0,0 +1,77 @@ +/* + * 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 LICENSE. + */ + +#ifndef _UTILS_UTILS_H +#define _UTILS_UTILS_H + +#include <stdbool.h> +#include <stdlib.h> +#include <stdarg.h> + +#define B_STRING_CHUNK_SIZE 128 + +typedef void (*b_free_func_t) (void *ptr); + +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; +    b_free_func_t free_func; +} b_trie_t; + +b_slist_t* b_slist_append(b_slist_t *l, void *data); +void b_slist_free_full(b_slist_t *l, b_free_func_t free_func); +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(b_free_func_t free_func); +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)); + +void* b_malloc(size_t size); +void* b_realloc(void *ptr, size_t size); + +#endif /* _UTILS_UTILS_H */ | 
