aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-03-09 08:00:53 +0800
committerGitHub <noreply@github.com>2025-03-09 08:00:53 +0800
commit8ea18119e7bbbf956680266b6e1a69bc5fa4b40d (patch)
tree91101e0d0fee56dc6552beda3e922810d8775c9a /src
parente02ee7410a6d04b32ec38af9f4ffdcf0798a0f0b (diff)
downloadrneovim-8ea18119e7bbbf956680266b6e1a69bc5fa4b40d.tar.gz
rneovim-8ea18119e7bbbf956680266b6e1a69bc5fa4b40d.tar.bz2
rneovim-8ea18119e7bbbf956680266b6e1a69bc5fa4b40d.zip
vim-patch:9.1.1184: Unnecessary use of vim_tolower() in vim_strnicmp_asc() (#32792)
Problem: Unnecessary use of vim_tolower() in vim_strnicmp_asc(). Solution: Use TOLOWER_ASC() instead (zeertzjq). It was passing *s1 and *s2 to vim_tolower(). When char is signed, which is the case on most platforms, c < 0x80 is always true, so it already behaves the same as TOLOWER_ASC(). closes: vim/vim#16826 https://github.com/vim/vim/commit/b7dc5d3b6169efc8aa0b9d86476072877e74bc2c Use this function for hashy case-insensitive lookup, as it's ASCII-only. Note that this function doesn't cast TOLOWER_ASC() argument to uint8_t, so it'll treat a UTF-8 byte as smaller than NUL. It doesn't matter, as one of the strings being compared is ASCII-only, and its behavior still leads to consistent ordering.
Diffstat (limited to 'src')
-rw-r--r--src/gen/hashy.lua4
-rw-r--r--src/nvim/strings.c22
2 files changed, 24 insertions, 2 deletions
diff --git a/src/gen/hashy.lua b/src/gen/hashy.lua
index 48292bfc0e..7fdb00699f 100644
--- a/src/gen/hashy.lua
+++ b/src/gen/hashy.lua
@@ -129,14 +129,14 @@ function M.hashy_hash(name, strings, access, lower)
}
}
return -1;
-]]):format(lower and 'mb_strnicmp' or 'memcmp', access('i')))
+]]):format(lower and 'vim_strnicmp_asc' or 'memcmp', access('i')))
else
put(([[
if (low < 0 || %s(str, %s, len)) {
return -1;
}
return low;
-]]):format(lower and 'mb_strnicmp' or 'memcmp', access('low')))
+]]):format(lower and 'vim_strnicmp_asc' or 'memcmp', access('low')))
end
put '}\n\n'
return neworder, table.concat(stats)
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 322b97d6bf..add4c9dcb6 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -475,6 +475,28 @@ bool striequal(const char *a, const char *b)
return (a == NULL && b == NULL) || (a && b && STRICMP(a, b) == 0);
}
+/// Compare two ASCII strings, for length "len", ignoring case, ignoring locale.
+///
+/// @return 0 for match, < 0 for smaller, > 0 for bigger
+int vim_strnicmp_asc(const char *s1, const char *s2, size_t len)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ int i = 0;
+ while (len > 0) {
+ i = TOLOWER_ASC(*s1) - TOLOWER_ASC(*s2);
+ if (i != 0) {
+ break; // this character is different
+ }
+ if (*s1 == NUL) {
+ break; // strings match until NUL
+ }
+ s1++;
+ s2++;
+ len--;
+ }
+ return i;
+}
+
/// strchr() version which handles multibyte strings
///
/// @param[in] string String to search in.