summaryrefslogtreecommitdiffstats
path: root/acf2/path.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf2/path.lua')
-rw-r--r--acf2/path.lua111
1 files changed, 111 insertions, 0 deletions
diff --git a/acf2/path.lua b/acf2/path.lua
new file mode 100644
index 0000000..a31687d
--- /dev/null
+++ b/acf2/path.lua
@@ -0,0 +1,111 @@
+--[[
+Copyright (c) 2012-2013 Kaarle Ritvanen
+See LICENSE file for license details
+--]]
+
+local M = {}
+
+local map = require('acf2.util').map
+
+
+local up = {}
+M.wildcard = {}
+local special = {['..']=up, ['*']=M.wildcard}
+
+
+function M.is_absolute(path) return path:sub(1, 1) == '/' end
+
+
+function M.escape(comp)
+ for symbol, item in pairs(special) do
+ if comp == item then return symbol end
+ end
+ if type(comp) == 'number' then return tostring(comp) end
+ local res = comp:gsub('([\\/])', '\\%1')
+ return (special[res] or tonumber(res)) and '\\'..res or res
+end
+
+
+function M.rawjoin(p1, p2, ...)
+ if not p2 then return p1 end
+ if not M.is_absolute(p2) then p2 = '/'..p2 end
+ return M.rawjoin((p1 == '/' and '' or p1)..p2, ...)
+end
+
+function M.join(parent, ...)
+ return M.rawjoin(parent, unpack(map(M.escape, {...})))
+end
+
+
+function M.split(path)
+ local res = {}
+ local comp = ''
+ local escaped
+
+ local function merge(s)
+ if s > '' then
+ table.insert(res, not escaped and (special[s] or tonumber(s)) or s)
+ end
+ end
+
+ while true do
+ local prefix, sep, suffix = path:match('([^\\/]*)([\\/])(.*)')
+ if not prefix then
+ merge(comp..path)
+ return res
+ end
+
+ comp = comp..prefix
+ if sep == '\\' then
+ comp = comp..suffix:sub(1, 1)
+ escaped = true
+ path = suffix:sub(2, -1)
+ else
+ merge(comp)
+ comp = ''
+ escaped = false
+ path = suffix
+ end
+ end
+end
+
+
+function M.is_unique(path)
+ for _, comp in ipairs(M.split(path)) do
+ if comp == M.wildcard then return false end
+ end
+ return true
+end
+
+
+function M.to_absolute(path, base)
+ if not M.is_absolute(path) then
+ path = base..(base ~= '/' and '/' or '')..path
+ end
+ local comps = M.split(path)
+ local i = 1
+ while i <= #comps do
+ if comps[i] == up then
+ if i == 1 then error('Invalid path: '..path) end
+ table.remove(comps, i - 1)
+ table.remove(comps, i - 1)
+ i = i - 1
+ else i = i + 1 end
+ end
+ return M.join('/', unpack(comps))
+end
+
+
+function M.parent(path)
+ local comps = M.split(path)
+ table.remove(comps)
+ return M.join('/', unpack(comps))
+end
+
+function M.name(path)
+ local comps = M.split(path)
+ return comps[#comps]
+end
+
+
+return M