git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 04/16] refactor skip_prefix to return a boolean

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Jun 20, 2014, 01:59 UTC
Message-ID
<CAPig+cTKgrYx1hcO-hV3ZT2sm1rR17bWJC0ktZzFQB=TMr6Xuw@mail.gmail.com>
In-Reply-To
<20140618194417.GD22622@sigill.intra.peff.net>
On Wed, Jun 18, 2014 at 3:44 PM, Jeff King <peff@peff.net> wrote:
Show 51 quoted lines
> The skip_prefix function returns a pointer to the content
> past the prefix, or NULL if the prefix was not found. While
> this is nice and simple, in practice it makes it hard to use
> for two reasons:
>
>   1. When you want to conditionally skip or keep the string
>      as-is, you have to introduce a second temporary
>      variable. For example:
>
>        tmp = skip_prefix(buf, "foo");
>        if (tmp)
>                buf = tmp;
>
>   2. It is verbose to check the outcome in a conditional, as
>      you need extra parentheses to silence compiler
>      warnings. For example:
>
>        if ((cp = skip_prefix(buf, "foo"))
>                /* do something with cp */
>
> Both of these make it harder to use for long if-chains, and
> we tend to use starts_with instead. However, the first line
> of "do something" is often to then skip forward in buf past
> the prefix, either using a magic constant or with an extra
> strlen (which is generally computed at compile time, but
> means we are repeating ourselves).
>
> This patch refactors skip_prefix to return a simple boolean,
> and to provide the pointer value as an out-parameter. If the
> prefix is not found, the out-parameter is untouched. This
> lets you write:
>
>   if (skip_prefix(arg, "foo ", &arg))
>           do_foo(arg);
>   else if (skip_prefix(arg, "bar ", &arg))
>           do_bar(arg);
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> diff --git a/git-compat-util.h b/git-compat-util.h
> index b6f03b3..556c839 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -349,13 +349,31 @@ 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 "str" begins with "prefix", return 1. If out is non-NULL,
> + * it it set to str + strlen(prefix) (i.e., the prefix is skipped).

The documentation claims that 'out' can be NULL, however, the code does not respect this. NULL 'out' seems rather pointless (unless you want an alias for starts_with()), so presumably the documentation is incorrect.

Show 28 quoted lines
> + *
> + * Otherwise, returns 0 and out is left 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 defined(NO_MMAP) || defined(USE_WIN32_MMAP)
Previous: Jeff KingNext: Jeff King
Message 6 of 33 in “skip_prefix refactoring and cleanups”
  1. 0/16 skip_prefix refactoring and cleanupsJeff King, Jun 18, 2014
  2. 01/16 parse_diff_color_slot: drop ofs parameterJeff King, Jun 18, 2014
  3. 02/16 daemon: mark some strings as constJeff King, Jun 18, 2014
  4. 03/16 avoid using skip_prefix as a booleanJeff King, Jun 18, 2014
  5. 04/16 refactor skip_prefix to return a booleanJeff King, Jun 18, 2014
  6. Eric SunshineJun 20, 2014
  7. Jeff KingJun 20, 2014
  8. Eric SunshineJun 20, 2014
  9. Jeff KingJun 20, 2014
  10. Junio C HamanoJun 23, 2014
  11. Jeff KingJun 23, 2014
  12. builtin/clone.c: detect a clone starting at a tag correctlyJunio C Hamano, Jun 23, 2014
  13. 05/16 apply: use skip_prefix instead of raw additionJeff King, Jun 18, 2014
  14. 06/16 fast-import: fix read of uninitialized argv memoryJeff King, Jun 18, 2014
  15. 07/16 transport-helper: avoid reading past end-of-stringJeff King, Jun 18, 2014
  16. 08/16 use skip_prefix to avoid magic numbersJeff King, Jun 18, 2014
  17. Junio C HamanoJun 23, 2014
  18. Jeff KingJul 1, 2014
  19. 09/16 use skip_prefix to avoid repeating stringsJeff King, Jun 18, 2014
  20. 10/16 fast-import: use skip_prefix for parsing inputJeff King, Jun 18, 2014
  21. Eric SunshineJun 20, 2014
  22. Jeff KingJun 20, 2014
  23. Eric SunshineJun 20, 2014
  24. 11/16 daemon: use skip_prefix to avoid magic numbersJeff King, Jun 18, 2014
  25. 12/16 stat_opt: check extra strlen callJeff King, Jun 18, 2014
  26. 13/16 fast-import: refactor parsing of spacesJeff King, Jun 18, 2014
  27. 14/16 fetch-pack: refactor parsing in get_ackJeff King, Jun 18, 2014
  28. Eric SunshineJun 20, 2014
  29. 15/16 git: avoid magic number with skip_prefixJeff King, Jun 18, 2014
  30. 16/16 use skip_prefix to avoid repeated calculationsJeff King, Jun 18, 2014
  31. Tanay AbhraJun 19, 2014
  32. 17/16 http-push: refactor parsing of remote object namesJeff King, Jun 19, 2014
  33. Jeff KingJun 19, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.