[strings] Add optimized utilities to deal with path extensions
This commit is contained in:
parent
f6e031a98a
commit
12a12197df
94
strings.lua
94
strings.lua
|
@ -8,6 +8,100 @@ local strings = {}
|
|||
|
||||
-- Platform preferred path separator
|
||||
local SEP = package.config:sub(1,1)
|
||||
local DOT = string.byte('.')
|
||||
local SLASH = string.byte('/')
|
||||
local BACKSLASH = string.byte('\\')
|
||||
local COLON = string.byte(':')
|
||||
|
||||
--- Find file extension within path.
|
||||
--
|
||||
-- @string path a file path
|
||||
-- @string[opt] sep path separator pattern, any combination of '/', '\\' or ':' to support various OSes, defaults to all
|
||||
-- @treturn number extension position within path if an extension is found, nil otherwise
|
||||
function strings.findpathext(path, sep)
|
||||
sep = sep or '/\\:'
|
||||
for i = 1,#sep do
|
||||
local byt = sep:byte(i)
|
||||
if byt ~= SLASH and byt ~= BACKSLASH and byt ~= COLON then
|
||||
error(("Unsupported path separator pattern: %q"):format(sep))
|
||||
end
|
||||
end
|
||||
|
||||
local function issep(byt)
|
||||
for i = 1,#sep do
|
||||
if byt == sep:byte(i) then return true end
|
||||
end
|
||||
end
|
||||
|
||||
local pos = nil
|
||||
|
||||
for i = #path,2,-1 do
|
||||
local byt = path:byte(i)
|
||||
|
||||
if byt == DOT and not issep(path:byte(i-1)) then
|
||||
-- Update extension position
|
||||
pos = i
|
||||
elseif issep(byt) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
--- Set default file extension.
|
||||
--
|
||||
-- If path contains an extension, returns the path unaltered,
|
||||
-- otherwise set extension to the specified one.
|
||||
--
|
||||
-- @string path a file path
|
||||
-- @string ext default extension to be set
|
||||
-- @string[opt] sep path separator pattern, any combination of '/', '\\' or ':' to support various OSes, defaults to all
|
||||
-- @treturn string updated path, and separator position
|
||||
function strings.setdefpathext(path, ext, sep)
|
||||
if ext:byte(1) ~= DOT then
|
||||
error(("Bad extension %q: must be a string starting with '.'"):format(ext))
|
||||
end
|
||||
|
||||
local pos = strings.findpathext(path, sep)
|
||||
if not pos then
|
||||
-- Append default extension
|
||||
pos = #path
|
||||
path = path..ext
|
||||
end
|
||||
|
||||
return path, pos
|
||||
end
|
||||
|
||||
--- Set file extension.
|
||||
--
|
||||
-- @string path a file path
|
||||
-- @string ext extension to be set (including '.')
|
||||
-- @string[opt] sep path separator pattern, any combination of '/', '\\' or ':' to support various OSes, defaults to all
|
||||
-- @treturn string updated path and separator position
|
||||
function strings.setpathext(path, ext, sep)
|
||||
if ext:byte(1) ~= DOT then
|
||||
error(("Bad extension %q: must be a string starting with '.'"):format(ext))
|
||||
end
|
||||
|
||||
local pos = strings.findpathext(path, sep)
|
||||
if pos then
|
||||
-- Trim existing extension
|
||||
path = path:sub(1, pos-1)
|
||||
end
|
||||
|
||||
return path..ext, pos
|
||||
end
|
||||
|
||||
--- Get file extension.
|
||||
--
|
||||
-- @string path a file path
|
||||
-- @string[opt] sep path separator pattern, any combination of '/', '\\' or ':' to support various OSes, defaults to all
|
||||
-- @treturn string file extension and position, if any is found, nil otherwise
|
||||
function strings.getpathext(path, sep)
|
||||
local pos = strings.findpathext(path, sep)
|
||||
if pos then return path:sub(pos), pos end
|
||||
end
|
||||
|
||||
--- Remove redundant slashes and resolve dot and dot-dots in path.
|
||||
--
|
||||
|
|
Loading…
Reference in New Issue