diff --git a/core_backup.c b/core_backup.c index 7f083fdc69..e660292414 100644 --- a/core_backup.c +++ b/core_backup.c @@ -279,9 +279,7 @@ bool core_backup_get_backup_crc(char *backup_path, uint32_t *crc) goto error; /* Convert to an integer */ - *crc = (uint32_t)string_hex_to_unsigned(crc_str); - - if (*crc == 0) + if ((*crc = (uint32_t)string_hex_to_unsigned(crc_str)) == 0) goto error; string_list_free(metadata_list); diff --git a/core_updater_list.c b/core_updater_list.c index 841abdd11d..54438aea78 100644 --- a/core_updater_list.c +++ b/core_updater_list.c @@ -371,9 +371,7 @@ static bool core_updater_list_set_crc( if (!entry || string_is_empty(crc_str)) return false; - crc = (uint32_t)string_hex_to_unsigned(crc_str); - - if (crc == 0) + if ((crc = (uint32_t)string_hex_to_unsigned(crc_str)) == 0) return false; entry->crc = crc; diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index 86295751ea..0b2f953788 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -82,7 +82,11 @@ struct path_linked_list* path_linked_list_new(void) return paths_list; } -/* Free the entire linked list */ +/** + * path_linked_list_free: + * + * Free the entire linked list + **/ void path_linked_list_free(struct path_linked_list *in_path_linked_list) { struct path_linked_list *node_tmp = (struct path_linked_list*)in_path_linked_list; @@ -99,11 +103,14 @@ void path_linked_list_free(struct path_linked_list *in_path_linked_list) } /** + * path_linked_list_add_path: + * * Add a node to the linked list with this path * If the first node's path if it's not yet set the path * on this node instead **/ -void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, char *path) +void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, + char *path) { /* If the first item does not have a path this is a list which has just been created, so we just fill @@ -142,9 +149,9 @@ void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, cha * Find delimiter of an archive file. Only the first '#' * after a compression extension is considered. * - * Returns: pointer to the delimiter in the path if it contains + * @return pointer to the delimiter in the path if it contains * a path inside a compressed file, otherwise NULL. - */ + **/ const char *path_get_archive_delim(const char *path) { char buf[5]; @@ -198,8 +205,8 @@ const char *path_get_archive_delim(const char *path) * Gets extension of file. Only '.'s * after the last slash are considered. * - * Returns: extension part from the path. - */ + * @return extension part from the path. + **/ const char *path_get_extension(const char *path) { const char *ext; @@ -216,12 +223,12 @@ const char *path_get_extension(const char *path) * text after and including the last '.'. * Only '.'s after the last slash are considered. * - * Returns: + * @return * 1) If path has an extension, returns path with the * extension removed. * 2) If there is no extension, returns NULL. * 3) If path is empty or NULL, returns NULL - */ + **/ char *path_remove_extension(char *path) { char *last = !string_is_empty(path) @@ -239,7 +246,7 @@ char *path_remove_extension(char *path) * * Checks if path is a compressed file. * - * Returns: true (1) if path is a compressed file, otherwise false (0). + * @return true if path is a compressed file, otherwise false. **/ bool path_is_compressed_file(const char* path) { @@ -286,6 +293,17 @@ void fill_pathname(char *out_path, const char *in_path, } +/** + * find_last_slash: + * @str : path + * @size : size of path + * + * Find last slash in path. Tries to find + * a backslash on Windows too which takes precedence + * over regular slash. + + * @return pointer to last slash/backslash found in @str. + **/ char *find_last_slash(const char *str) { const char *slash = strrchr(str, '/'); @@ -362,7 +380,7 @@ size_t fill_pathname_dir(char *in_dir, const char *in_basename, * * Copies basename of @in_path into @out_path. * - * @return length of the string copied into @out + * @return Length of the string copied into @out **/ size_t fill_pathname_base(char *out, const char *in_path, size_t size) { @@ -398,7 +416,8 @@ void fill_pathname_basedir(char *out_dir, * * Copies only the parent directory name of @in_dir into @out_dir. * The two buffers must not overlap. Removes trailing '/'. - * Returns true on success, false if a slash was not found in the path. + * + * @return true on success, false if a slash was not found in the path. **/ bool fill_pathname_parent_dir_name(char *out_dir, const char *in_dir, size_t size) @@ -446,7 +465,8 @@ bool fill_pathname_parent_dir_name(char *out_dir, * * Copies parent directory of @in_dir into @out_dir. * Assumes @in_dir is a directory. Keeps trailing '/'. - * If the path was already at the root directory, @out_dir will be an empty string. + * If the path was already at the root directory, + * @out_dir will be an empty string. **/ void fill_pathname_parent_dir(char *out_dir, const char *in_dir, size_t size) @@ -506,16 +526,15 @@ void fill_str_dated_filename(char *out_filename, rtime_localtime(&cur_time, &tm_); + strlcpy(out_filename, in_str, size); if (string_is_empty(ext)) { strftime(format, sizeof(format), "-%y%m%d-%H%M%S", &tm_); - strlcpy(out_filename, in_str, size); strlcat(out_filename, format, size); } else { strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", &tm_); - strlcpy(out_filename, in_str, size); strlcat(out_filename, format, size); strlcat(out_filename, ext, size); } @@ -584,7 +603,7 @@ void path_parent_dir(char *path, size_t len) * * Get basename from @path. * - * Returns: basename from path. + * @return basename from path. **/ const char *path_basename(const char *path) { @@ -604,6 +623,15 @@ const char *path_basename(const char *path) } /* Specialized version */ +/** + * path_basename_nocompression: + * @path : path + * + * Specialized version of path_basename(). + * Get basename from @path. + * + * @return basename from path. + **/ const char *path_basename_nocompression(const char *path) { /* We cut at the last slash */ @@ -619,7 +647,7 @@ const char *path_basename_nocompression(const char *path) * * Checks if @path is an absolute path or a relative path. * - * Returns: true if path is absolute, false if path is relative. + * @return true if path is absolute, false if path is relative. **/ bool path_is_absolute(const char *path) { @@ -655,7 +683,7 @@ bool path_is_absolute(const char *path) * * Relative paths are rebased on the current working dir. * - * Returns: @buf if successful, NULL otherwise. + * @return @buf if successful, NULL otherwise. * Note: Not implemented on consoles * Note: Symlinks are only resolved on Unix-likes * Note: The current working dir might not be what you expect, @@ -921,9 +949,9 @@ size_t fill_pathname_join_delim(char *out_path, const char *dir, size_t copied; /* behavior of strlcpy is undefined if dst and src overlap */ if (out_path == dir) - copied = strlen(dir); + copied = strlen(dir); else - copied = strlcpy(out_path, dir, size); + copied = strlcpy(out_path, dir, size); out_path[copied] = delim; out_path[copied+1] = '\0'; @@ -1060,28 +1088,53 @@ void fill_pathname_abbreviate_special(char *out_path, retro_assert(strlcpy(out_path, in_path, size) < size); } -/* Changes the slashes to the correct kind for the os - * So forward slash on linux and backslash on Windows */ +/** + * pathname_conform_slashes_to_os: + * + * @path : path + * + * Leaf function. + * + * Changes the slashes to the correct kind for the os + * So forward slash on linux and backslash on Windows + **/ void pathname_conform_slashes_to_os(char *path) { /* Conform slashes to os standard so we get proper matching */ - char* p; + char *p; for (p = path; *p; p++) if (*p == '/' || *p == '\\') *p = PATH_DEFAULT_SLASH_C(); } -/* Change all shashes to forward so they are more portable between Windows and Linux */ +/** + * pathname_make_slashes_portable: + * @path : path + * + * Leaf function. + * + * Change all slashes to forward so they are more + * portable between Windows and Linux + **/ void pathname_make_slashes_portable(char *path) { /* Conform slashes to os standard so we get proper matching */ - char* p; + char *p; for (p = path; *p; p++) if (*p == '/' || *p == '\\') *p = '/'; } -/* Get the number of slashes in a path, returns an integer */ +/** + * get_pathname_num_slashes: + * @in_path : input path + * + * Leaf function. + * + * Get the number of slashes in a path. + * + * @return number of slashes found in @in_path. + **/ static int get_pathname_num_slashes(const char *in_path) { int num_slashes = 0; @@ -1098,11 +1151,18 @@ static int get_pathname_num_slashes(const char *in_path) return num_slashes; } -/* Fills the supplied path with either the abbreviated path or the relative path, which ever - * one is has less depth / number of slashes - * If lengths of abbreviated and relative paths are the same the relative path will be used - * in_path can be an absolute, relative or abbreviated path */ -void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size) +/** + * fill_pathname_abbreviated_or_relative: + * + * Fills the supplied path with either the abbreviated path or + * the relative path, which ever one has less depth / number of slashes + * + * If lengths of abbreviated and relative paths are the same, + * the relative path will be used + * @in_path can be an absolute, relative or abbreviated path + **/ +void fill_pathname_abbreviated_or_relative(char *out_path, + const char *in_refpath, const char *in_path, size_t size) { char in_path_conformed[PATH_MAX_LENGTH]; char in_refpath_conformed[PATH_MAX_LENGTH]; @@ -1111,15 +1171,13 @@ void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpat char relative_path[PATH_MAX_LENGTH]; char abbreviated_path[PATH_MAX_LENGTH]; - in_path_conformed[0] = '\0'; - in_refpath_conformed[0] = '\0'; expanded_path[0] = '\0'; absolute_path[0] = '\0'; relative_path[0] = '\0'; abbreviated_path[0] = '\0'; - strcpy_literal(in_path_conformed, in_path); - strcpy_literal(in_refpath_conformed, in_refpath); + strlcpy(in_path_conformed, in_path, sizeof(in_path_conformed)); + strlcpy(in_refpath_conformed, in_refpath, sizeof(in_refpath_conformed)); pathname_conform_slashes_to_os(in_path_conformed); pathname_conform_slashes_to_os(in_refpath_conformed); diff --git a/libretro-common/include/file/file_path.h b/libretro-common/include/file/file_path.h index f77cfb2b60..8687f716c0 100644 --- a/libretro-common/include/file/file_path.h +++ b/libretro-common/include/file/file_path.h @@ -103,12 +103,12 @@ bool path_is_compressed_file(const char *path); * path_get_archive_delim: * @path : path * - * Gets delimiter of an archive file. Only the first '#' + * Find delimiter of an archive file. Only the first '#' * after a compression extension is considered. * - * Returns: pointer to the delimiter in the path if it contains - * a compressed file, otherwise NULL. - */ + * @return pointer to the delimiter in the path if it contains + * a path inside a compressed file, otherwise NULL. + **/ const char *path_get_archive_delim(const char *path); /** @@ -118,8 +118,12 @@ const char *path_get_archive_delim(const char *path); * Gets extension of file. Only '.'s * after the last slash are considered. * - * Returns: extension part from the path. - */ + * Hidden non-leaf function cost: + * - calls string_is_empty + * - calls strrchr + * + * @return extension part from the path. + **/ const char *path_get_extension(const char *path); /** @@ -130,7 +134,10 @@ const char *path_get_extension(const char *path); * text after and including the last '.'. * Only '.'s after the last slash are considered. * - * Returns: + * Hidden non-leaf function cost: + * - calls strrchr + * + * @return * 1) If path has an extension, returns path with the * extension removed. * 2) If there is no extension, returns NULL. @@ -144,9 +151,26 @@ char *path_remove_extension(char *path); * * Get basename from @path. * - * Returns: basename from path. + * Hidden non-leaf function cost: + * - Calls path_get_archive_delim() + * - can call find_last_slash once if it returns NULL + * + * @return basename from path. **/ const char *path_basename(const char *path); + +/** + * path_basename_nocompression: + * @path : path + * + * Specialized version of path_basename(). + * Get basename from @path. + * + * Hidden non-leaf function cost: + * - Calls find_last_slash + * + * @return basename from path. + **/ const char *path_basename_nocompression(const char *path); /** @@ -179,7 +203,7 @@ void path_parent_dir(char *path, size_t len); * * Relative paths are rebased on the current working dir. * - * Returns: @buf if successful, NULL otherwise. + * @return @buf if successful, NULL otherwise. * Note: Not implemented on consoles * Note: Symlinks are only resolved on Unix-likes * Note: The current working dir might not be what you expect, @@ -202,7 +226,8 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks); * * E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp **/ -size_t path_relative_to(char *out, const char *path, const char *base, size_t size); +size_t path_relative_to(char *out, const char *path, const char *base, + size_t size); /** * path_is_absolute: @@ -210,7 +235,7 @@ size_t path_relative_to(char *out, const char *path, const char *base, size_t si * * Checks if @path is an absolute path or a relative path. * - * Returns: true if path is absolute, false if path is relative. + * @return true if path is absolute, false if path is relative. **/ bool path_is_absolute(const char *path); @@ -234,6 +259,11 @@ bool path_is_absolute(const char *path); * out_path = "/foo/bar/baz/boo.asm" * E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => * out_path = "/foo/bar/baz/boo" + * + * Hidden non-leaf function cost: + * - calls strlcpy 2x + * - calls strrchr + * - calls strlcat */ void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size); @@ -249,6 +279,12 @@ void fill_pathname(char *out_path, const char *in_path, * * E.g.: * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}" + * + * Hidden non-leaf function cost: + * - Calls rtime_localtime() + * - Calls strftime + * - Calls strlcat + * **/ size_t fill_dated_filename(char *out_filename, const char *ext, size_t size); @@ -265,17 +301,31 @@ size_t fill_dated_filename(char *out_filename, * * E.g.: * out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}" + * + * Hidden non-leaf function cost: + * - Calls time + * - Calls rtime_localtime + * - Calls strlcpy + * - Calls string_is_empty + * - Calls strftime + * - Calls strlcat at least 2x **/ void fill_str_dated_filename(char *out_filename, const char *in_str, const char *ext, size_t size); /** * find_last_slash: - * @str : input path + * @str : path + * @size : size of path * - * Gets a pointer to the last slash in the input path. + * Find last slash in path. Tries to find + * a backslash on Windows too which takes precedence + * over regular slash. + + * Hidden non-leaf function cost: + * - calls strrchr * - * Returns: a pointer to the last slash in the input path. + * @return pointer to last slash/backslash found in @str. **/ char *find_last_slash(const char *str); @@ -295,6 +345,11 @@ char *find_last_slash(const char *str); * * E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c", * replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm" + * + * Hidden non-leaf function cost: + * - Calls fill_pathname_slash() + * - Calls path_basename() + * - Calls strlcat 2x **/ size_t fill_pathname_dir(char *in_dir, const char *in_basename, const char *replace, size_t size); @@ -306,6 +361,12 @@ size_t fill_pathname_dir(char *in_dir, const char *in_basename, * @size : size of output path * * Copies basename of @in_path into @out_path. + * + * Hidden non-leaf function cost: + * - Calls path_basename() + * - Calls strlcpy + * + * @return length of the string copied into @out **/ size_t fill_pathname_base(char *out_path, const char *in_path, size_t size); @@ -318,6 +379,10 @@ size_t fill_pathname_base(char *out_path, const char *in_path, size_t size); * Copies base directory of @in_path into @out_path. * If in_path is a path without any slashes (relative current directory), * @out_path will get path "./". + * + * Hidden non-leaf function cost: + * - Calls strlcpy + * - Calls path_basedir() **/ void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); @@ -329,7 +394,13 @@ void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); * * Copies only the parent directory name of @in_dir into @out_dir. * The two buffers must not overlap. Removes trailing '/'. - * Returns true on success, false if a slash was not found in the path. + * + * Hidden non-leaf function cost: + * - Calls strdup + * - Calls find_last_slash x times + * - Can call strlcpy + * + * @return true on success, false if a slash was not found in the path. **/ bool fill_pathname_parent_dir_name(char *out_dir, const char *in_dir, size_t size); @@ -343,6 +414,11 @@ bool fill_pathname_parent_dir_name(char *out_dir, * Copies parent directory of @in_dir into @out_dir. * Assumes @in_dir is a directory. Keeps trailing '/'. * If the path was already at the root directory, @out_dir will be an empty string. + * + * Hidden non-leaf function cost: + * - Can call strlcpy if (@out_dir != @in_dir) + * - Calls strlen if (@out_dir == @in_dir) + * - Calls path_parent_dir() **/ void fill_pathname_parent_dir(char *out_dir, const char *in_dir, size_t size); @@ -372,6 +448,11 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, * Joins a directory (@dir) and path (@path) together. * Makes sure not to get two consecutive slashes * between directory and path. + * + * Hidden non-leaf function cost: + * - calls strlcpy + * - calls fill_pathname_slash() + * - calls strlcat **/ size_t fill_pathname_join(char *out_path, const char *dir, const char *path, size_t size); @@ -391,6 +472,11 @@ size_t fill_pathname_join_special_ext(char *out_path, * * Joins a directory (@dir) and path (@path) together * using the given delimiter (@delim). + * + * Hidden non-leaf function cost: + * - can call strlen + * - can call strlcpy + * - can call strlcat **/ size_t fill_pathname_join_delim(char *out_path, const char *dir, const char *path, const char delim, size_t size); @@ -401,10 +487,40 @@ void fill_pathname_expand_special(char *out_path, void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size); -void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size); +/** + * fill_pathname_abbreviated_or_relative: + * + * Fills the supplied path with either the abbreviated path or + * the relative path, which ever one has less depth / number of slashes + * + * If lengths of abbreviated and relative paths are the same, + * the relative path will be used + * @in_path can be an absolute, relative or abbreviated path + **/ +void fill_pathname_abbreviated_or_relative(char *out_path, + const char *in_refpath, const char *in_path, size_t size); +/** + * pathname_conform_slashes_to_os: + * + * @path : path + * + * Leaf function. + * + * Changes the slashes to the correct kind for the os + * So forward slash on linux and backslash on Windows + **/ void pathname_conform_slashes_to_os(char *path); +/** + * pathname_make_slashes_portable: + * @path : path + * + * Leaf function. + * + * Change all slashes to forward so they are more + * portable between Windows and Linux + **/ void pathname_make_slashes_portable(char *path); /** @@ -422,8 +538,8 @@ void path_basedir_wrapper(char *path); * * Checks if character (@c) is a slash. * - * Returns: true (1) if character is a slash, otherwise false (0). - */ + * @return true if character is a slash, otherwise false. + **/ #ifdef _WIN32 #define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\')) #else @@ -435,8 +551,8 @@ void path_basedir_wrapper(char *path); * * Gets the default slash separator. * - * Returns: default slash separator. - */ + * @return default slash separator. + **/ #ifdef _WIN32 #define PATH_DEFAULT_SLASH() "\\" #define PATH_DEFAULT_SLASH_C() '\\' @@ -452,6 +568,11 @@ void path_basedir_wrapper(char *path); * * Assumes path is a directory. Appends a slash * if not already there. + + * Hidden non-leaf function cost: + * - calls find_last_slash() + * - can call strlcat once if it returns false + * - calls strlen **/ void fill_pathname_slash(char *path, size_t size); @@ -467,7 +588,7 @@ void fill_pathname_home_dir(char *buf, size_t size); * * Create directory on filesystem. * - * Returns: true (1) if directory could be created, otherwise false (0). + * @return true if directory could be created, otherwise false. **/ bool path_mkdir(const char *dir); @@ -477,7 +598,7 @@ bool path_mkdir(const char *dir); * * Checks if path is a directory. * - * Returns: true (1) if path is a directory, otherwise false (0). + * @return true if path is a directory, otherwise false. */ bool path_is_directory(const char *path); diff --git a/libretro-common/include/string/stdstring.h b/libretro-common/include/string/stdstring.h index 6431f4aa72..7b5873ce16 100644 --- a/libretro-common/include/string/stdstring.h +++ b/libretro-common/include/string/stdstring.h @@ -92,16 +92,20 @@ static INLINE bool string_ends_with_size(const char *str, const char *suffix, static INLINE bool string_ends_with(const char *str, const char *suffix) { - if (!str || !suffix) - return false; - return string_ends_with_size(str, suffix, strlen(str), strlen(suffix)); + return str && suffix && string_ends_with_size(str, suffix, strlen(str), strlen(suffix)); } -/* Returns the length of 'str' (c.f. strlen()), but only +/** + * strlen_size: + * + * Leaf function. + * + * @return the length of 'str' (c.f. strlen()), but only * checks the first 'size' characters * - If 'str' is NULL, returns 0 * - If 'str' is not NULL and no '\0' character is found - * in the first 'size' characters, returns 'size' */ + * in the first 'size' characters, returns 'size' + **/ static INLINE size_t strlen_size(const char *str, size_t size) { size_t i = 0; @@ -158,16 +162,30 @@ char *string_ucwords(char *s); char *string_replace_substring(const char *in, const char *pattern, const char *by); -/* Remove leading whitespaces */ +/** + * string_trim_whitespace_left: + * + * Remove leading whitespaces + **/ char *string_trim_whitespace_left(char *const s); -/* Remove trailing whitespaces */ +/** + * string_trim_whitespace_right: + * + * Remove trailing whitespaces + **/ char *string_trim_whitespace_right(char *const s); -/* Remove leading and trailing whitespaces */ +/** + * string_trim_whitespace: + * + * Remove leading and trailing whitespaces + **/ char *string_trim_whitespace(char *const s); -/* +/** + * word_wrap: + * * Wraps string specified by 'src' to destination buffer * specified by 'dst' and 'dst_size'. * This function assumes that all glyphs in the string @@ -184,11 +202,13 @@ char *string_trim_whitespace(char *const s); * compatibility with word_wrap_wideglyph(). * @param max_lines max lines of destination string. * 0 means no limit. - */ + **/ void word_wrap(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines); -/* +/** + * word_wrap_wideglyph: + * * Wraps string specified by 'src' to destination buffer * specified by 'dst' and 'dst_size'. * This function assumes that all glyphs in the string @@ -219,14 +239,17 @@ void word_wrap(char *dst, size_t dst_size, const char *src, * would be 200 * @param max_lines max lines of destination string. * 0 means no limit. - */ + **/ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines); -/* Splits string into tokens seperated by 'delim' +/** + * string_tokenize: + * + * Splits string into tokens seperated by @delim * > Returned token string must be free()'d * > Returns NULL if token is not found - * > After each call, 'str' is set to the position after the + * > After each call, @str is set to the position after the * last found token * > Tokens *include* empty strings * Usage example: @@ -239,48 +262,118 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, * free(token); * token = NULL; * } - */ + **/ char* string_tokenize(char **str, const char *delim); -/* Removes every instance of character 'c' from 'str' */ +/** + * string_remove_all_chars: + * @str : input string (must be non-NULL, otherwise UB) + * + * Leaf function. + * + * Removes every instance of character @c from @str + **/ void string_remove_all_chars(char *str, char c); -/* Replaces every instance of character 'find' in 'str' - * with character 'replace' */ +/** + * string_replace_all_chars: + * @str : input string (must be non-NULL, otherwise UB) + * @find : character to find + * @replace : character to replace @find with + * + * Hidden non-leaf function cost: + * - Calls strchr (in a loop) + * + * Replaces every instance of character @find in @str + * with character @replace + **/ void string_replace_all_chars(char *str, char find, char replace); -/* Converts string to unsigned integer. - * Returns 0 if string is invalid */ +/** + * string_to_unsigned: + * @str : input string + * + * Converts string to unsigned integer. + * + * @return 0 if string is invalid, otherwise > 0 + **/ unsigned string_to_unsigned(const char *str); -/* Converts hexadecimal string to unsigned integer. +/** + * string_hex_to_unsigned: + * @str : input string (must be non-NULL, otherwise UB) + * + * Converts hexadecimal string to unsigned integer. * Handles optional leading '0x'. - * Returns 0 if string is invalid */ + * + * @return 0 if string is invalid, otherwise > 0 + **/ unsigned string_hex_to_unsigned(const char *str); char *string_init(const char *src); void string_set(char **string, const char *src); -/* Get the total number of occurrences of a character in the given string. */ +/** + * string_count_occurrences_single_character: + * + * Leaf function. + * + * Get the total number of occurrences of character @c in @str. + * + * @return Total number of occurrences of character @c + */ int string_count_occurrences_single_character(const char *str, char c); -/* Replaces all spaces with the given character. */ +/** + * string_replace_whitespace_with_single_character: + * + * Leaf function. + * + * Replaces all spaces with given character @c. + **/ void string_replace_whitespace_with_single_character(char *str, char c); -/* Replaces multiple spaces with a single space in a string. */ +/** + * string_replace_multi_space_with_single_space: + * + * Leaf function. + * + * Replaces multiple spaces with a single space in a string. + **/ void string_replace_multi_space_with_single_space(char *str); -/* Remove all spaces from the given string. */ +/** + * string_remove_all_whitespace: + * + * Leaf function. + * + * Remove all spaces from the given string. + **/ void string_remove_all_whitespace(char *str_trimmed, const char *str); /* Retrieve the last occurance of the given character in a string. */ int string_index_last_occurance(const char *str, char c); -/* Find the position of a substring in a string. */ +/** + * string_find_index_substring_string: + * @str : input string (must be non-NULL, otherwise UB) + * @substr : substring to find in @str + * + * Hidden non-leaf function cost: + * - Calls strstr + * + * Find the position of substring @substr in string @str. + **/ int string_find_index_substring_string(const char *str, const char *substr); -/* Strips non-ASCII characters from a string. */ +/** + * string_copy_only_ascii: + * + * Leaf function. + * + * Strips non-ASCII characters from a string. + **/ void string_copy_only_ascii(char *str_stripped, const char *str); extern const unsigned char lr_char_props[256]; diff --git a/libretro-common/string/stdstring.c b/libretro-common/string/stdstring.c index c8806e08bb..d800042b64 100644 --- a/libretro-common/string/stdstring.c +++ b/libretro-common/string/stdstring.c @@ -136,7 +136,11 @@ char *string_replace_substring(const char *in, return out; } -/* Remove leading whitespaces */ +/** + * string_trim_whitespace_left: + * + * Remove leading whitespaces + **/ char *string_trim_whitespace_left(char *const s) { if (s && *s) @@ -157,7 +161,11 @@ char *string_trim_whitespace_left(char *const s) return s; } -/* Remove trailing whitespaces */ +/** + * string_trim_whitespace_right: + * + * Remove trailing whitespaces + **/ char *string_trim_whitespace_right(char *const s) { if (s && *s) @@ -177,7 +185,11 @@ char *string_trim_whitespace_right(char *const s) return s; } -/* Remove leading and trailing whitespaces */ +/** + * string_trim_whitespace: + * + * Remove leading and trailing whitespaces + **/ char *string_trim_whitespace(char *const s) { string_trim_whitespace_right(s); /* order matters */ @@ -186,7 +198,28 @@ char *string_trim_whitespace(char *const s) return s; } -void word_wrap(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines) +/** + * word_wrap: + * + * Wraps string specified by 'src' to destination buffer + * specified by 'dst' and 'dst_size'. + * This function assumes that all glyphs in the string + * have an on-screen pixel width similar to that of + * regular Latin characters - i.e. it will not wrap + * correctly any text containing so-called 'wide' Unicode + * characters (e.g. CJK languages, emojis, etc.). + * + * @param dst pointer to destination buffer. + * @param dst_size size of destination buffer. + * @param src pointer to input string. + * @param line_width max number of characters per line. + * @param wideglyph_width not used, but is necessary to keep + * compatibility with word_wrap_wideglyph(). + * @param max_lines max lines of destination string. + * 0 means no limit. + **/ +void word_wrap(char *dst, size_t dst_size, const char *src, + int line_width, int wideglyph_width, unsigned max_lines) { char *lastspace = NULL; unsigned counter = 0; @@ -261,7 +294,43 @@ void word_wrap(char *dst, size_t dst_size, const char *src, int line_width, int *dst = '\0'; } -void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines) +/** + * word_wrap_wideglyph: + * + * Wraps string specified by 'src' to destination buffer + * specified by 'dst' and 'dst_size'. + * This function assumes that all glyphs in the string + * are: + * - EITHER 'non-wide' Unicode glyphs, with an on-screen + * pixel width similar to that of regular Latin characters + * - OR 'wide' Unicode glyphs (e.g. CJK languages, emojis, etc.) + * with an on-screen pixel width defined by 'wideglyph_width' + * Note that wrapping may occur in inappropriate locations + * if 'src' string contains 'wide' Unicode characters whose + * on-screen pixel width deviates greatly from the set + * 'wideglyph_width' value. + * + * @param dst pointer to destination buffer. + * @param dst_size size of destination buffer. + * @param src pointer to input string. + * @param line_width max number of characters per line. + * @param wideglyph_width effective width of 'wide' Unicode glyphs. + * the value here is normalised relative to the + * typical on-screen pixel width of a regular + * Latin character: + * - a regular Latin character is defined to + * have an effective width of 100 + * - wideglyph_width = 100 * (wide_character_pixel_width / latin_character_pixel_width) + * - e.g. if 'wide' Unicode characters in 'src' + * have an on-screen pixel width twice that of + * regular Latin characters, wideglyph_width + * would be 200 + * @param max_lines max lines of destination string. + * 0 means no limit. + **/ +void word_wrap_wideglyph(char *dst, size_t dst_size, + const char *src, int line_width, + int wideglyph_width, unsigned max_lines) { char *lastspace = NULL; char *lastwideglyph = NULL; @@ -310,7 +379,7 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_w break; if (*src == ' ') - lastspace = dst; /* Remember the location of the whitespace */ + lastspace = dst; /* Remember the location of the whitespace */ else if (*src == '\n') { /* If newlines embedded in the input, @@ -330,7 +399,7 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_w { /* Remember the location of the first byte * whose length as UTF-8 >= 3*/ - lastwideglyph = dst; + lastwideglyph = dst; counter_normalized += additional_counter_normalized; } @@ -349,9 +418,9 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_w /* Insert newline character */ *lastwideglyph = '\n'; lines++; - src -= dst - lastwideglyph; - dst = lastwideglyph + 1; - lastwideglyph = NULL; + src -= dst - lastwideglyph; + dst = lastwideglyph + 1; + lastwideglyph = NULL; /* Early return if remaining src string * length is less than line width */ @@ -367,9 +436,9 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_w * with newline character */ *lastspace = '\n'; lines++; - src -= dst - lastspace - 1; - dst = lastspace + 1; - lastspace = NULL; + src -= dst - lastspace - 1; + dst = lastspace + 1; + lastspace = NULL; /* Early return if remaining src string * length is less than line width */ @@ -385,10 +454,13 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_w *dst = '\0'; } -/* Splits string into tokens seperated by 'delim' +/** + * string_tokenize: + * + * Splits string into tokens seperated by @delim * > Returned token string must be free()'d * > Returns NULL if token is not found - * > After each call, 'str' is set to the position after the + * > After each call, @str is set to the position after the * last found token * > Tokens *include* empty strings * Usage example: @@ -401,7 +473,7 @@ void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_w * free(token); * token = NULL; * } - */ + **/ char* string_tokenize(char **str, const char *delim) { /* Taken from https://codereview.stackexchange.com/questions/216956/strtok-function-thread-safe-supports-empty-tokens-doesnt-change-string# */ @@ -440,42 +512,53 @@ char* string_tokenize(char **str, const char *delim) return token; } -/* Removes every instance of character 'c' from 'str' */ +/** + * string_remove_all_chars: + * @str : input string (must be non-NULL, otherwise UB) + * + * Leaf function. + * + * Removes every instance of character @c from @str + **/ void string_remove_all_chars(char *str, char c) { - char *read_ptr = NULL; - char *write_ptr = NULL; - - if (string_is_empty(str)) - return; - - read_ptr = str; - write_ptr = str; + char *read_ptr = str; + char *write_ptr = str; while (*read_ptr != '\0') { *write_ptr = *read_ptr++; - write_ptr += (*write_ptr != c) ? 1 : 0; + if (*write_ptr != c) + write_ptr++; } *write_ptr = '\0'; } -/* Replaces every instance of character 'find' in 'str' - * with character 'replace' */ +/** + * string_replace_all_chars: + * @str : input string (must be non-NULL, otherwise UB) + * @find : character to find + * @replace : character to replace @find with + * + * Replaces every instance of character @find in @str + * with character @replace + **/ void string_replace_all_chars(char *str, char find, char replace) { - if (!string_is_empty(str)) - { - char *str_ptr = str; - while ((str_ptr = strchr(str_ptr, find))) - *str_ptr++ = replace; - } - + char *str_ptr = str; + while ((str_ptr = strchr(str_ptr, find))) + *str_ptr++ = replace; } -/* Converts string to unsigned integer. - * Returns 0 if string is invalid */ +/** + * string_to_unsigned: + * @str : input string + * + * Converts string to unsigned integer. + * + * @return 0 if string is invalid, otherwise > 0 + **/ unsigned string_to_unsigned(const char *str) { const char *ptr = NULL; @@ -492,25 +575,33 @@ unsigned string_to_unsigned(const char *str) return (unsigned)strtoul(str, NULL, 10); } -/* Converts hexadecimal string to unsigned integer. +/** + * string_hex_to_unsigned: + * @str : input string (must be non-NULL, otherwise UB) + * + * Converts hexadecimal string to unsigned integer. * Handles optional leading '0x'. - * Returns 0 if string is invalid */ + * + * @return 0 if string is invalid, otherwise > 0 + **/ unsigned string_hex_to_unsigned(const char *str) { const char *hex_str = str; const char *ptr = NULL; - if (string_is_empty(str)) - return 0; - /* Remove leading '0x', if required */ - if (strlen(str) >= 2) + if (str[0] != '\0' && str[1] != '\0') + { if ( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) + { hex_str = str + 2; - - if (string_is_empty(hex_str)) + if (string_is_empty(hex_str)) + return 0; + } + } + else return 0; /* Check for valid characters */ @@ -524,7 +615,13 @@ unsigned string_hex_to_unsigned(const char *str) } /** - * Get the total number of occurrences of a character in the given string. + * string_count_occurrences_single_character: + * + * Leaf function. + * + * Get the total number of occurrences of character @c in @str. + * + * @return Total number of occurrences of character @c */ int string_count_occurrences_single_character(const char *str, char c) { @@ -538,8 +635,12 @@ int string_count_occurrences_single_character(const char *str, char c) } /** - * Replaces all spaces with the given character. - */ + * string_replace_whitespace_with_single_character: + * + * Leaf function. + * + * Replaces all spaces with given character @c. + **/ void string_replace_whitespace_with_single_character(char *str, char c) { for (; *str; str++) @@ -548,8 +649,12 @@ void string_replace_whitespace_with_single_character(char *str, char c) } /** + * string_replace_multi_space_with_single_space: + * + * Leaf function. + * * Replaces multiple spaces with a single space in a string. - */ + **/ void string_replace_multi_space_with_single_space(char *str) { char *str_trimmed = str; @@ -568,8 +673,12 @@ void string_replace_multi_space_with_single_space(char *str) } /** + * string_remove_all_whitespace: + * + * Leaf function. + * * Remove all spaces from the given string. - */ + **/ void string_remove_all_whitespace(char *str_trimmed, const char *str) { for (; *str; str++) @@ -589,22 +698,27 @@ int string_index_last_occurance(const char *str, char c) } /** - * Find the position of a substring in a string. - */ + * string_find_index_substring_string: + * @str : input string (must be non-NULL, otherwise UB) + * @substr : substring to find in @str + * + * Find the position of substring @substr in string @str. + **/ int string_find_index_substring_string(const char *str, const char *substr) { - if (!string_is_empty(str)) - { - const char *pos = strstr(str, substr); - - if (pos) - return pos - str; - } - + const char *pos = strstr(str, substr); + if (pos) + return pos - str; return -1; } -/* Strips non-ASCII characters from a string. */ +/** + * string_copy_only_ascii: + * + * Leaf function. + * + * Strips non-ASCII characters from a string. + **/ void string_copy_only_ascii(char *str_stripped, const char *str) { for (; *str; str++)