Refactor normalize_path_copy_len() by extracting helpers for skipping slashes, handling dot components, and stripping the previous path component, making the control flow easier to follow.
This is a mechanical refactor only; there are no functional changes. Behavior is unchanged, as verified by t0060-path-utils.sh.
Signed-off-by: Pushkar Singh <pushkarkumarsingh1970@gmail.com> --- path.c | 105 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 38 deletions(-)
Show changes to path.c +67 −38
diff --git a/path.c b/path.c index d726537622..00845cc03f 100644 --- a/path.c +++ b/path.c @@ -1112,6 +1112,63 @@ const char *remove_leading_path(const char *in, const char *prefix) * end with a '/', then the callers need to be fixed up accordingly. * */ + +static const char *skip_slashes(const char *p) +{ + while (is_dir_sep(*p)) + p++; + return p; +} + +static int handle_dot_component(const char **src) +{ + const char *s = *src; + + if (*s != '.') + return 0; + + if (!s[1]) { + *src = s + 1; + return 1; + } + + if (is_dir_sep(s[1])) { + *src = skip_slashes(s + 2); + return 1; + } + + if (s[1] == '.') { + if (!s[2]) { + *src = s + 2; + return 2; + } + if (is_dir_sep(s[2])) { + *src = skip_slashes(s + 3); + return 2; + } + } + + return 0; +} + +static int strip_last_component(char **dst, char *dst0, int *prefix_len) +{ + char *d = *dst; + + d--; + if (d <= dst0) + return -1; + + while (dst0 < d && d[-1] != '/') + d--; + + if (prefix_len && *prefix_len > d - dst0) + *prefix_len = d - dst0; + + *dst = d; + return 0; +} + int normalize_path_copy_len(char *dst, const char *src, int *prefix_len) { char *dst0; @@ -1129,8 +1186,7 @@ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len) } dst0 = dst; - while (is_dir_sep(*src)) - src++; + src = skip_slashes(src); for (;;) { char c = *src; @@ -1143,29 +1199,14 @@ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len) * (3) ".." and ends -- strip one and terminate. * (4) "../" -- strip one, eat slash and continue. */ - if (c == '.') { - if (!src[1]) { - /* (1) */ - src++; - } else if (is_dir_sep(src[1])) { - /* (2) */ - src += 2; - while (is_dir_sep(*src)) - src++; - continue; - } else if (src[1] == '.') { - if (!src[2]) { - /* (3) */ - src += 2; - goto up_one; - } else if (is_dir_sep(src[2])) { - /* (4) */ - src += 3; - while (is_dir_sep(*src)) - src++; - goto up_one; - } - } + int dot = handle_dot_component(&src); + + if (dot == 1) + continue; + if (dot == 2) { + if (strip_last_component(&dst, dst0, prefix_len)) + return -1; + continue; } /* copy up to the next '/', and eat all '/' */ @@ -1180,20 +1221,8 @@ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len) break; continue; - up_one: - /* - * dst0..dst is prefix portion, and dst[-1] is '/'; - * go up one level. - */ - dst--; /* go to trailing '/' */ - if (dst <= dst0) - return -1; - /* Windows: dst[-1] cannot be backslash anymore */ - while (dst0 < dst && dst[-1] != '/') - dst--; - if (prefix_len && *prefix_len > dst - dst0) - *prefix_len = dst - dst0; } + *dst = '\0'; return 0; }
-- 2.43.0