From 35480f0b23f2c1824109ddae24392a70d19c6b9c Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 30 Jun 2014 12:57:51 -0400 Subject: add strip_suffix function Many callers of ends_with want to not only find out whether a string has a suffix, but want to also strip it off. Doing that separately has two minor problems: 1. We often run over the string twice (once to find the suffix, and then once more to find its length to subtract the suffix length). 2. We have to specify the suffix length again, which means either a magic number, or repeating ourselves with strlen("suffix"). Just as we have skip_prefix to avoid these cases with starts_with, we can add a strip_suffix to avoid them with ends_with. Note that we add two forms of strip_suffix here: one that takes a string, with the resulting length as an out-parameter; and one that takes a pointer/length pair, and reuses the length as an out-parameter. The latter is more efficient when the caller already has the length (e.g., when using strbufs), but it can be easy to confuse the two, as they take the same number and types of parameters. For that reason, the "mem" form puts its length parameter next to the buffer (since they are a pair), and the string form puts it at the end (since it is an out-parameter). The compiler can notice when you get the order wrong, which should help prevent writing one when you meant the other. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-compat-util.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'git-compat-util.h') diff --git a/git-compat-util.h b/git-compat-util.h index e6a4159a25..4c451b575d 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -350,6 +350,33 @@ static inline const char *skip_prefix(const char *str, const char *prefix) return NULL; } +/* + * If buf ends with suffix, return 1 and subtract the length of the suffix + * from *len. Otherwise, return 0 and leave *len untouched. + */ +static inline int strip_suffix_mem(const char *buf, size_t *len, + const char *suffix) +{ + size_t suflen = strlen(suffix); + if (*len < suflen || memcmp(buf + (*len - suflen), suffix, suflen)) + return 0; + *len -= suflen; + return 1; +} + +/* + * If str ends with suffix, return 1 and set *len to the size of the string + * without the suffix. Otherwise, return 0 and set *len to the size of the + * string. + * + * Note that we do _not_ NUL-terminate str to the new length. + */ +static inline int strip_suffix(const char *str, const char *suffix, size_t *len) +{ + *len = strlen(str); + return strip_suffix_mem(str, len, suffix); +} + #if defined(NO_MMAP) || defined(USE_WIN32_MMAP) #ifndef PROT_READ -- cgit v1.2.1 From f52a35fd63cc6d570083cedc15576d01c0968d98 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 30 Jun 2014 12:58:08 -0400 Subject: implement ends_with via strip_suffix The ends_with function is essentially a simplified version of strip_suffix, in which we throw away the stripped length. Implementing it as an inline on top of strip_suffix has two advantages: 1. We save a bit of duplicated code. 2. The suffix is typically a string literal, and we call strlen on it. By making the function inline, many compilers can replace the strlen call with a constant. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-compat-util.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'git-compat-util.h') diff --git a/git-compat-util.h b/git-compat-util.h index 4c451b575d..1c9c68cb89 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -339,7 +339,6 @@ extern void set_error_routine(void (*routine)(const char *err, va_list params)); extern void set_die_is_recursing_routine(int (*routine)(void)); extern int starts_with(const char *str, const char *prefix); -extern int ends_with(const char *str, const char *suffix); static inline const char *skip_prefix(const char *str, const char *prefix) { @@ -377,6 +376,12 @@ static inline int strip_suffix(const char *str, const char *suffix, size_t *len) return strip_suffix_mem(str, len, suffix); } +static inline int ends_with(const char *str, const char *suffix) +{ + size_t len; + return strip_suffix(str, suffix, &len); +} + #if defined(NO_MMAP) || defined(USE_WIN32_MMAP) #ifndef PROT_READ -- cgit v1.2.1 From 2975c770ca609ea5afc80631c4ac9087c527b6fd Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 30 Jun 2014 12:58:25 -0400 Subject: replace has_extension with ends_with These two are almost the same function, with the exception that has_extension only matches if there is content before the suffix. So ends_with(".exe", ".exe") is true, but has_extension would not be. This distinction does not matter to any of the callers, though, and we can just replace uses of has_extension with ends_with. We prefer the "ends_with" name because it is more generic, and there is nothing about the function that requires it to be used for file extensions. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-compat-util.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'git-compat-util.h') diff --git a/git-compat-util.h b/git-compat-util.h index 1c9c68cb89..47a49c355d 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -578,13 +578,6 @@ static inline size_t xsize_t(off_t len) return (size_t)len; } -static inline int has_extension(const char *filename, const char *ext) -{ - size_t len = strlen(filename); - size_t extlen = strlen(ext); - return len > extlen && !memcmp(filename + len - extlen, ext, extlen); -} - /* in ctype.c, for kwset users */ extern const char tolower_trans_tbl[256]; -- cgit v1.2.1