aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames <89495599+IAKOBVS@users.noreply.github.com>2024-06-08 09:12:39 +0700
committerGitHub <noreply@github.com>2024-06-08 10:12:39 +0800
commit4881211097aba7f5d17700362ec0967e3024f074 (patch)
tree3afe9a6c2be2f5c801b127d38ae940129deed3d6
parentda6f68ee6966ebf434eee840b22a4f45e61d77dd (diff)
downloadrneovim-4881211097aba7f5d17700362ec0967e3024f074.tar.gz
rneovim-4881211097aba7f5d17700362ec0967e3024f074.tar.bz2
rneovim-4881211097aba7f5d17700362ec0967e3024f074.zip
refactor: quadratic behavior in vim_findfile_stopdir (#29232)
Copies characters in-places instead. Related #27827
-rw-r--r--src/nvim/file_search.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 51bea3111c..30a80773e3 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -505,24 +505,36 @@ error_return:
/// @return the stopdir string. Check that ';' is not escaped.
char *vim_findfile_stopdir(char *buf)
{
- char *r_ptr = buf;
-
- while (*r_ptr != NUL && *r_ptr != ';') {
- if (r_ptr[0] == '\\' && r_ptr[1] == ';') {
- // Overwrite the escape char,
- // use strlen(r_ptr) to move the trailing NUL.
- STRMOVE(r_ptr, r_ptr + 1);
- r_ptr++;
+ for (; *buf != NUL && *buf != ';' && (buf[0] != '\\' || buf[1] != ';'); buf++) {}
+ char *dst = buf;
+ if (*buf == ';') {
+ goto is_semicolon;
+ }
+ if (*buf == NUL) {
+ goto is_nul;
+ }
+ goto start;
+ while (*buf != NUL && *buf != ';') {
+ if (buf[0] == '\\' && buf[1] == ';') {
+start:
+ // Overwrite the escape char.
+ *dst++ = ';';
+ buf += 2;
+ } else {
+ *dst++ = *buf++;
}
- r_ptr++;
}
- if (*r_ptr == ';') {
- *r_ptr = 0;
- r_ptr++;
- } else if (*r_ptr == NUL) {
- r_ptr = NULL;
+ assert(dst < buf);
+ *dst = NUL;
+ if (*buf == ';') {
+is_semicolon:
+ *buf = NUL;
+ buf++;
+ } else { // if (*buf == NUL)
+is_nul:
+ buf = NULL;
}
- return r_ptr;
+ return buf;
}
/// Clean up the given search context. Can handle a NULL pointer.