From 279270ae5fb1eb196b3749f1dee07bb6e8baaee9 Mon Sep 17 00:00:00 2001 From: libretroadmin Date: Tue, 24 Dec 2024 06:14:26 +0100 Subject: [PATCH] string_list_join_concat_special - specialized version without bounds check --- libretro-common/include/lists/string_list.h | 28 ++++++++--- libretro-common/lists/string_list.c | 52 ++++++++++++++++----- menu/menu_displaylist.c | 12 ++--- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/libretro-common/include/lists/string_list.h b/libretro-common/include/lists/string_list.h index f772193e22..275b3d39a3 100644 --- a/libretro-common/include/lists/string_list.h +++ b/libretro-common/include/lists/string_list.h @@ -104,7 +104,7 @@ bool string_split_noalloc(struct string_list *list, **/ struct string_list *string_separate(char *str, const char *delim); -bool string_separate_noalloc(struct string_list *list, +bool string_separate_noalloc(struct string_list *list, char *str, const char *delim); bool string_list_deinitialize(struct string_list *list); @@ -166,23 +166,39 @@ void string_list_free(struct string_list *list); /** * string_list_join_concat: - * @buffer : buffer that @list will be joined to. - * @size : length of @buffer. + * @s : buffer that @list will be joined to. + * @len : length of @s. * @list : pointer to string list. * @delim : delimiter character for @list. * * A string list will be joined/concatenated as a - * string to @buffer, delimited by @delim. + * string to @s, delimited by @delim. * - * NOTE: @buffer must be NULL-terminated. + * NOTE: @s must be NULL-terminated. * * Hidden non-leaf function cost: * - Calls strlen_size() * - Calls strlcat x times in a loop **/ -void string_list_join_concat(char *buffer, size_t size, +void string_list_join_concat(char *s, size_t len, const struct string_list *list, const char *sep); +/** + * string_list_join_concat: + * @s : buffer that @list will be joined to. + * @len : length of @s. + * @list : pointer to string list. + * @delim : delimiter character for @list. + * + * Specialized version of string_list_join_concat + * without the bounds check. + * + * A string list will be joined/concatenated as a + * string to @s, delimited by @delim. + **/ +void string_list_join_concat_special(char *s, size_t len, + const struct string_list *list, const char *delim); + /** * string_list_set: * @list : pointer to string list diff --git a/libretro-common/lists/string_list.c b/libretro-common/lists/string_list.c index e092cfcd32..ade9bfb6c5 100644 --- a/libretro-common/lists/string_list.c +++ b/libretro-common/lists/string_list.c @@ -241,38 +241,66 @@ void string_list_set(struct string_list *list, /** * string_list_join_concat: - * @buffer : buffer that @list will be joined to. - * @size : length of @buffer. + * @s : buffer that @list will be joined to. + * @len : length of @s. * @list : pointer to string list. * @delim : delimiter character for @list. * * A string list will be joined/concatenated as a * string to @buffer, delimited by @delim. **/ -void string_list_join_concat(char *buffer, size_t size, +void string_list_join_concat(char *s, size_t len, const struct string_list *list, const char *delim) { size_t i; - size_t len = strlen_size(buffer, size); + size_t _len = strlen_size(s, len); - /* If buffer is already 'full', nothing + /* If @s is already 'full', nothing * further can be added * > This condition will also be triggered - * if buffer is not NULL-terminated, + * if @s is not NULL-terminated, * in which case any attempt to increment - * buffer or decrement size would lead to + * @s or decrement @len would lead to * undefined behaviour */ - if (len >= size) + if (_len >= len) return; - buffer += len; - size -= len; + s += _len; + len -= _len; for (i = 0; i < list->size; i++) { - size_t _len = strlcat(buffer, list->elems[i].data, size); + size_t __len = strlcat(s, list->elems[i].data, len); if ((i + 1) < list->size) - strlcpy(buffer + _len, delim, size - _len); + strlcpy(s + __len, delim, len - __len); + } +} + +/** + * string_list_join_concat: + * @s : buffer that @list will be joined to. + * @len : length of @s. + * @list : pointer to string list. + * @delim : delimiter character for @list. + * + * Specialized version of string_list_join_concat + * without the bounds check. + * + * A string list will be joined/concatenated as a + * string to @s, delimited by @delim. + * + * TODO/FIXME - eliminate the strlcat + **/ +void string_list_join_concat_special(char *s, size_t len, + const struct string_list *list, const char *delim) +{ + size_t i; + + for (i = 0; i < list->size; i++) + { + size_t __len = strlcat(s, list->elems[i].data, len); + if ((i + 1) < list->size) + strlcpy(s + __len, delim, len - __len); } } diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 9cde3aae7d..3b00251d96 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -634,7 +634,7 @@ static int menu_displaylist_parse_core_info( tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; - string_list_join_concat(tmp, sizeof(tmp), + string_list_join_concat_special(tmp + _len, sizeof(tmp) - _len, core_info->categories_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) @@ -649,7 +649,7 @@ static int menu_displaylist_parse_core_info( tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; - string_list_join_concat(tmp, sizeof(tmp), + string_list_join_concat_special(tmp + _len, sizeof(tmp) - _len, core_info->authors_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) @@ -664,7 +664,7 @@ static int menu_displaylist_parse_core_info( tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; - string_list_join_concat(tmp, sizeof(tmp), + string_list_join_concat_special(tmp + _len, sizeof(tmp) - _len, core_info->permissions_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) @@ -679,7 +679,7 @@ static int menu_displaylist_parse_core_info( tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; - string_list_join_concat(tmp, sizeof(tmp), + string_list_join_concat_special(tmp + _len, sizeof(tmp) - _len, core_info->licenses_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) @@ -695,7 +695,7 @@ static int menu_displaylist_parse_core_info( tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; - string_list_join_concat(tmp, sizeof(tmp), + string_list_join_concat_special(tmp + _len, sizeof(tmp) - _len, core_info->supported_extensions_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) @@ -710,7 +710,7 @@ static int menu_displaylist_parse_core_info( tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; - string_list_join_concat(tmp, sizeof(tmp), + string_list_join_concat_special(tmp + _len, sizeof(tmp) - _len, core_info->required_hw_api_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL))