diff --git a/string_list.c b/string_list.c new file mode 100644 index 0000000000..72128434c8 --- /dev/null +++ b/string_list.c @@ -0,0 +1,175 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2014 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include "miscellaneous.h" +#include "compat/strl.h" +#include "string_list.h" + +void string_list_free(struct string_list *list) +{ + size_t i; + if (!list) + return; + + for (i = 0; i < list->size; i++) + free(list->elems[i].data); + free(list->elems); + free(list); +} + +static bool string_list_capacity(struct string_list *list, size_t cap) +{ + rarch_assert(cap > list->size); + + struct string_list_elem *new_data = (struct string_list_elem*) + realloc(list->elems, cap * sizeof(*new_data)); + if (!new_data) + return false; + + list->elems = new_data; + list->cap = cap; + return true; +} + +struct string_list *string_list_new(void) +{ + struct string_list *list = (struct string_list*)calloc(1, sizeof(*list)); + if (!list) + return NULL; + + if (!string_list_capacity(list, 32)) + { + string_list_free(list); + return NULL; + } + + return list; +} + +bool string_list_append(struct string_list *list, const char *elem, + union string_list_elem_attr attr) +{ + if (list->size >= list->cap && + !string_list_capacity(list, list->cap * 2)) + return false; + + char *dup = strdup(elem); + if (!dup) + return false; + + list->elems[list->size].data = dup; + list->elems[list->size].attr = attr; + + list->size++; + return true; +} + +void string_list_set(struct string_list *list, unsigned index, const char *str) +{ + free(list->elems[index].data); + rarch_assert(list->elems[index].data = strdup(str)); +} + +void string_list_join_concat(char *buffer, size_t size, + const struct string_list *list, const char *sep) +{ + size_t len = strlen(buffer); + rarch_assert(len < size); + buffer += len; + size -= len; + + size_t i; + for (i = 0; i < list->size; i++) + { + strlcat(buffer, list->elems[i].data, size); + if ((i + 1) < list->size) + strlcat(buffer, sep, size); + } +} + +struct string_list *string_split(const char *str, const char *delim) +{ + char *copy = NULL; + const char *tmp = NULL; + + struct string_list *list = string_list_new(); + if (!list) + goto error; + + copy = strdup(str); + if (!copy) + goto error; + + char *save; + tmp = strtok_r(copy, delim, &save); + while (tmp) + { + union string_list_elem_attr attr; + memset(&attr, 0, sizeof(attr)); + + if (!string_list_append(list, tmp, attr)) + goto error; + + tmp = strtok_r(NULL, delim, &save); + } + + free(copy); + return list; + +error: + string_list_free(list); + free(copy); + return NULL; +} + +bool string_list_find_elem(const struct string_list *list, const char *elem) +{ + size_t i; + if (!list) + return false; + + for (i = 0; i < list->size; i++) + { + if (strcasecmp(list->elems[i].data, elem) == 0) + return true; + } + + return false; +} + +bool string_list_find_elem_prefix(const struct string_list *list, + const char *prefix, const char *elem) +{ + size_t i; + if (!list) + return false; + + char prefixed[PATH_MAX]; + snprintf(prefixed, sizeof(prefixed), "%s%s", prefix, elem); + + for (i = 0; i < list->size; i++) + { + if (strcasecmp(list->elems[i].data, elem) == 0 || + strcasecmp(list->elems[i].data, prefixed) == 0) + return true; + } + + return false; +} diff --git a/string_list.h b/string_list.h new file mode 100644 index 0000000000..e124b360cb --- /dev/null +++ b/string_list.h @@ -0,0 +1,70 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2014 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef __RARCH_STRING_LIST_H +#define __RARCH_STRING_LIST_H + +#include "boolean.h" + +#ifdef __cplusplus +extern "C" { +#endif + +union string_list_elem_attr +{ + bool b; + int i; + void *p; +}; + +struct string_list_elem +{ + char *data; + union string_list_elem_attr attr; +}; + +struct string_list +{ + struct string_list_elem *elems; + size_t size; + size_t cap; +}; + +bool string_list_find_elem(const struct string_list *list, const char *elem); + +bool string_list_find_elem_prefix(const struct string_list *list, + const char *prefix, const char *elem); + +struct string_list *string_split(const char *str, const char *delim); + +struct string_list *string_list_new(void); + +bool string_list_append(struct string_list *list, const char *elem, + union string_list_elem_attr attr); + +void string_list_free(struct string_list *list); + +void string_list_join_concat(char *buffer, size_t size, + const struct string_list *list, const char *sep); + +void string_list_set(struct string_list *list, unsigned index, + const char *str); + +#ifdef __cplusplus +} +#endif + +#endif