diff options
-rw-r--r-- | src/nvim/search.c | 25 | ||||
-rw-r--r-- | src/nvim/spell.c | 2 | ||||
-rw-r--r-- | src/nvim/strings.c | 21 | ||||
-rw-r--r-- | test/unit/search_spec.lua | 24 | ||||
-rw-r--r-- | test/unit/strings_spec.lua | 35 | ||||
-rw-r--r-- | third-party/CMakeLists.txt | 4 |
6 files changed, 83 insertions, 28 deletions
diff --git a/src/nvim/search.c b/src/nvim/search.c index 11d40c058c..c79ce08cd7 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -204,31 +204,6 @@ char_u *get_search_pat(void) return mr_pattern; } -/* - * Reverse text into allocated memory. - * Returns the allocated string. - * - * TODO(philix): move reverse_text() to strings.c - */ -char_u *reverse_text(char_u *s) FUNC_ATTR_NONNULL_RET -{ - /* - * Reverse the pattern. - */ - size_t len = STRLEN(s); - char_u *rev = xmalloc(len + 1); - size_t rev_i = len; - for (size_t s_i = 0; s_i < len; s_i++) { - const int mb_len = utfc_ptr2len((char *)s + s_i); - rev_i -= mb_len; - memmove(rev + rev_i, s + s_i, mb_len); - s_i += mb_len - 1; - } - rev[len] = NUL; - - return rev; -} - void save_re_pat(int idx, char_u *pat, int magic) { if (spats[idx].pat != pat) { diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 1ba29e3fc1..df3ee73a28 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -443,7 +443,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou MAXWLEN + 1); mi.mi_fwordlen = (int)STRLEN(mi.mi_fword); - if (camel_case) { + if (camel_case && mi.mi_fwordlen > 0) { // introduce a fake word end space into the folded word. mi.mi_fword[mi.mi_fwordlen - 1] = ' '; } diff --git a/src/nvim/strings.c b/src/nvim/strings.c index cde2059a9d..ab5beb17bc 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1507,3 +1507,24 @@ int kv_do_printf(StringBuilder *str, const char *fmt, ...) str->size += (size_t)printed; return printed; } + +/// Reverse text into allocated memory. +/// +/// @return the allocated string. +char_u *reverse_text(char_u *s) + FUNC_ATTR_NONNULL_RET +{ + // Reverse the pattern. + size_t len = STRLEN(s); + char_u *rev = xmalloc(len + 1); + size_t rev_i = len; + for (size_t s_i = 0; s_i < len; s_i++) { + const int mb_len = utfc_ptr2len((char *)s + s_i); + rev_i -= (size_t)mb_len; + memmove(rev + rev_i, s + s_i, (size_t)mb_len); + s_i += (size_t)mb_len - 1; + } + rev[len] = NUL; + + return rev; +} diff --git a/test/unit/search_spec.lua b/test/unit/search_spec.lua index 3c2d485e0e..ef5a0cb831 100644 --- a/test/unit/search_spec.lua +++ b/test/unit/search_spec.lua @@ -5,6 +5,8 @@ local to_cstr = helpers.to_cstr local eq = helpers.eq local search = helpers.cimport("./src/nvim/search.h") +local globals = helpers.cimport('./src/nvim/globals.h') +local ffi = helpers.ffi itp('pat_has_uppercase', function() -- works on empty string @@ -31,3 +33,25 @@ itp('pat_has_uppercase', function() eq(false, search.pat_has_uppercase(to_cstr("aa\\%Ab"))) eq(true, search.pat_has_uppercase(to_cstr("aab\\%AU"))) end) + +describe('search_regcomp', function() + local search_regcomp = function(pat, pat_save, pat_use, options ) + local regmatch = ffi.new("regmmatch_T") + local fail = search.search_regcomp(to_cstr(pat), pat_save, pat_use, options, regmatch) + return fail, regmatch + end + + local get_search_pat = function() + return helpers.internalize(search.get_search_pat()) + end + + itp("accepts regexp pattern with invalid utf", function() + --crafted to call reverse_text with invalid utf + globals.curwin.w_onebuf_opt.wo_rl = 1 + globals.curwin.w_onebuf_opt.wo_rlc = to_cstr('s') + globals.cmdmod.keeppatterns = 1 + local fail = search_regcomp("a\192", 0,0,0) + eq(1, fail) + eq("\192a", get_search_pat()) + end) +end) diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua index e085ac749d..b2c839f25c 100644 --- a/test/unit/strings_spec.lua +++ b/test/unit/strings_spec.lua @@ -150,3 +150,38 @@ describe('strcase_save()' , function() eq("a", strcase_save("\xc1\x81", false)) end) end) + +describe("reverse_text", function() + local reverse_text = function(str) + return helpers.internalize(strings.reverse_text(to_cstr(str))) + end + + itp("handles empty string", function() + eq("", reverse_text("")) + end) + + itp("handles simple cases", function() + eq("a", reverse_text("a")) + eq("ba", reverse_text("ab")) + end) + + itp("handles multibyte characters", function() + eq("bα", reverse_text("αb")) + eq("Yötön yö", reverse_text("öy nötöY")) + end) + + itp("handles combining chars", function() + local utf8_COMBINING_RING_ABOVE = "\204\138" + local utf8_COMBINING_RING_BELOW = "\204\165" + eq("bba" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "aa", + reverse_text("aaa" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "bb")) + end) + + itp("treats invalid utf as separate characters", function() + eq("\192ba", reverse_text("ab\192")) + end) + + itp("treats an incomplete utf continuation sequence as valid", function() + eq("\194ba", reverse_text("ab\194")) + end) +end) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 0464f90734..5004b7c00c 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -137,8 +137,8 @@ set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/c-4.0.0/m set(MSGPACK_SHA256 420fe35e7572f2a168d17e660ef981a589c9cbe77faa25eb34a520e1fcc032c8) # https://github.com/LuaJIT/LuaJIT/tree/v2.1 -set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/91bc6b8ad1f373c1ce9003dc024b2e21fad0e444.tar.gz) -set(LUAJIT_SHA256 81895031fdb87602c7dde52280259c60b1ffd1b5a8a3c2792d3e2390481163fa) +set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/4ef96cff887c268cc676f9b4b1dc9c54a693efd5.tar.gz) +set(LUAJIT_SHA256 ae913e33be80dded08a2fc368787f168305c22808519c962553bf4c8668e9856) set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz) set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333) |