From ce17feb1b3ecfb0344af9b9111a4b4d313d51d7a Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Sun, 25 Aug 2019 23:33:39 +0000 Subject: [PATCH] path: add a function to check for path suffix We have a function to strip the path suffix from a commit, but we don't have one to check for a path suffix. For a plain filename, we can use basename, but that requires an allocation, since POSIX allows it to modify its argument. Refactor strip_path_suffix into a helper function and a new function, ends_with_path_components, to meet this need. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- path.c | 57 +++++++++++++++++++++++++++++++++++++++------------------ path.h | 3 +++ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/path.c b/path.c index 25e97b8c3f..e3da1f3c4e 100644 --- a/path.c +++ b/path.c @@ -1220,6 +1220,43 @@ static inline int chomp_trailing_dir_sep(const char *path, int len) return len; } +/* + * If path ends with suffix (complete path components), returns the offset of + * the last character in the path before the suffix (sans trailing directory + * separators), and -1 otherwise. + */ +static ssize_t stripped_path_suffix_offset(const char *path, const char *suffix) +{ + int path_len = strlen(path), suffix_len = strlen(suffix); + + while (suffix_len) { + if (!path_len) + return -1; + + if (is_dir_sep(path[path_len - 1])) { + if (!is_dir_sep(suffix[suffix_len - 1])) + return -1; + path_len = chomp_trailing_dir_sep(path, path_len); + suffix_len = chomp_trailing_dir_sep(suffix, suffix_len); + } + else if (path[--path_len] != suffix[--suffix_len]) + return -1; + } + + if (path_len && !is_dir_sep(path[path_len - 1])) + return -1; + return chomp_trailing_dir_sep(path, path_len); +} + +/* + * Returns true if the path ends with components, considering only complete path + * components, and false otherwise. + */ +int ends_with_path_components(const char *path, const char *components) +{ + return stripped_path_suffix_offset(path, components) != -1; +} + /* * If path ends with suffix (complete path components), returns the * part before suffix (sans trailing directory separators). @@ -1227,25 +1264,9 @@ static inline int chomp_trailing_dir_sep(const char *path, int len) */ char *strip_path_suffix(const char *path, const char *suffix) { - int path_len = strlen(path), suffix_len = strlen(suffix); + ssize_t offset = stripped_path_suffix_offset(path, suffix); - while (suffix_len) { - if (!path_len) - return NULL; - - if (is_dir_sep(path[path_len - 1])) { - if (!is_dir_sep(suffix[suffix_len - 1])) - return NULL; - path_len = chomp_trailing_dir_sep(path, path_len); - suffix_len = chomp_trailing_dir_sep(suffix, suffix_len); - } - else if (path[--path_len] != suffix[--suffix_len]) - return NULL; - } - - if (path_len && !is_dir_sep(path[path_len - 1])) - return NULL; - return xstrndup(path, chomp_trailing_dir_sep(path, path_len)); + return offset == -1 ? NULL : xstrndup(path, offset); } int daemon_avoid_alias(const char *p) diff --git a/path.h b/path.h index 2ba6ca58c8..14d6dcad16 100644 --- a/path.h +++ b/path.h @@ -193,4 +193,7 @@ const char *git_path_merge_head(struct repository *r); const char *git_path_fetch_head(struct repository *r); const char *git_path_shallow(struct repository *r); + +int ends_with_path_components(const char *path, const char *components); + #endif /* PATH_H */