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)
+/*
+ * If the string "str" begins with the string found in "prefix", return 1.
+ * The "out" parameter is set to "str + strlen(prefix)" (i.e., to the point in
+ * the string right after the prefix).
+ *
+ * Otherwise, return 0 and leave "out" untouched.
+ *
+ * Examples:
+ *
+ * [extract branch name, fail if not a branch]
+ * if (!skip_prefix(ref, "refs/heads/", &branch)
+ * return -1;
+ *
+ * [skip prefix if present, otherwise use whole string]
+ * skip_prefix(name, "refs/heads/", &name);
+ */
+static inline int skip_prefix(const char *str, const char *prefix,
+ const char **out)
{
do {
- if (!*prefix)
- return str;
+ if (!*prefix) {
+ *out = str;
+ return 1;
+ }
} while (*str++ == *prefix++);
- return NULL;
+ return 0;
}
+ /*
+ * 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);
+ }
+
+ 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
len = buf.len;
while ((de = readdir(dir)) != NULL) {
- int entlen;
+ const char *ent;
+ size_t entlen;
- if (!starts_with(de->d_name, prefix))
+ if (!skip_prefix(de->d_name, prefix, &ent))
continue;
strbuf_setlen(&buf, len);
if (!is_executable(buf.buf))
continue;
- entlen = strlen(de->d_name) - prefix_len;
- strip_suffix(de->d_name, ".exe", &entlen);
+ entlen = strlen(ent);
- if (has_extension(ent, ".exe"))
- entlen -= 4;
++ strip_suffix(ent, ".exe", &entlen);
- add_cmdname(cmds, de->d_name + prefix_len, entlen);
+ add_cmdname(cmds, ent, entlen);
}
closedir(dir);
strbuf_release(&buf);
extern void strbuf_trim(struct strbuf *);
extern void strbuf_rtrim(struct strbuf *);
extern void strbuf_ltrim(struct strbuf *);
+extern int strbuf_reencode(struct strbuf *sb, const char *from, const char *to);
+extern void strbuf_tolower(struct strbuf *sb);
extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
+ static inline int strbuf_strip_suffix(struct strbuf *sb, const char *suffix)
+ {
+ if (strip_suffix_mem(sb->buf, &sb->len, suffix)) {
+ strbuf_setlen(sb, sb->len);
+ return 1;
+ } else
+ return 0;
+ }
+
/*
* Split str (of length slen) at the specified terminator character.
* Return a null-terminated array of pointers to strbuf objects