Skip to content

Commit

Permalink
feat: more accurate file sorting on windows (#798)
Browse files Browse the repository at this point in the history
  • Loading branch information
dyphire authored Dec 8, 2023
1 parent cef5694 commit d01eb25
Showing 1 changed file with 65 additions and 1 deletion.
66 changes: 65 additions & 1 deletion src/uosc/lib/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,62 @@

--- In place sorting of filenames
---@param filenames string[]
function sort_filenames(filenames)

----- winapi start -----
-- in windows system, we can use the sorting function provided by the win32 API
-- see https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strcmplogicalw
-- this function was taken from https://github.com/mpvnet-player/mpv.net/issues/575#issuecomment-1817413401
local winapi = {}

if state.platform == 'windows' then
-- is_ffi_loaded is false usually means the mpv builds without luajit
local is_ffi_loaded, ffi = pcall(require, 'ffi')

if is_ffi_loaded then
winapi = {
ffi = ffi,
C = ffi.C,
CP_UTF8 = 65001,
shlwapi = ffi.load('shlwapi'),
}

-- ffi code from https://github.com/po5/thumbfast, Mozilla Public License Version 2.0
ffi.cdef[[
int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr,
int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
int __stdcall StrCmpLogicalW(wchar_t *psz1, wchar_t *psz2);
]]

winapi.utf8_to_wide = function(utf8_str)
if utf8_str then
local utf16_len = winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, utf8_str, -1, nil, 0)

if utf16_len > 0 then
local utf16_str = winapi.ffi.new('wchar_t[?]', utf16_len)

if winapi.C.MultiByteToWideChar(winapi.CP_UTF8, 0, utf8_str, -1, utf16_str, utf16_len) > 0 then
return utf16_str
end
end
end

return ''
end
end
end
----- winapi end -----

function sort_filenames_windows(filenames)
table.sort(filenames, function(a, b)
local a_wide = winapi.utf8_to_wide(a)
local b_wide = winapi.utf8_to_wide(b)
return winapi.shlwapi.StrCmpLogicalW(a_wide, b_wide) == -1
end)

return filenames
end

function sort_filenames_lua(filenames)
-- alphanum sorting for humans in Lua
-- http://notebook.kulchenko.com/algorithms/alphanumeric-natural-sorting-for-humans-in-lua
local function padnum(n, d)
Expand All @@ -24,6 +79,15 @@ function sort_filenames(filenames)
return filenames
end

function sort_filenames(filenames)
local is_ffi_loaded = pcall(require, 'ffi')
if state.platform == 'windows' and is_ffi_loaded then
sort_filenames_windows(filenames)
else
sort_filenames_lua(filenames)
end
end

-- Creates in-between frames to animate value from `from` to `to` numbers.
---@param from number
---@param to number|fun():number
Expand Down

0 comments on commit d01eb25

Please sign in to comment.