diff options
Diffstat (limited to 'src/utils/strings.c')
-rw-r--r-- | src/utils/strings.c | 283 |
1 files changed, 283 insertions, 0 deletions
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; +} |