summaryrefslogtreecommitdiffstats
path: root/aconf/path/base.lua
diff options
context:
space:
mode:
authorKaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>2015-02-09 19:44:12 +0200
committerKaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>2015-02-12 16:32:41 +0200
commit29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6 (patch)
treea8ad7d5343c41950ff9c8f96a55f41a80271f72a /aconf/path/base.lua
parent07a0eb180872401b271de40190603df8f3ab3db2 (diff)
downloadaconf-29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6.tar.bz2
aconf-29282b5a7d43e8b5ce12b0ec4b7a7620c19a67b6.tar.xz
proper escaping for back-end addresses
Diffstat (limited to 'aconf/path/base.lua')
-rw-r--r--aconf/path/base.lua159
1 files changed, 159 insertions, 0 deletions
diff --git a/aconf/path/base.lua b/aconf/path/base.lua
new file mode 100644
index 0000000..4e2bf8f
--- /dev/null
+++ b/aconf/path/base.lua
@@ -0,0 +1,159 @@
+--[[
+Copyright (c) 2012-2015 Kaarle Ritvanen
+See LICENSE file for license details
+--]]
+
+local M = {}
+
+
+local object = require('aconf.object')
+local class = object.class
+
+local map = require('aconf.util').map
+
+
+M.Special = class()
+function M.Special:tostring() return self.symbol end
+
+local Up = class(M.Special)
+Up.symbol = '..'
+
+local Wildcard = class(M.Special)
+Wildcard.symbol = '*'
+
+
+
+M.Syntax = class()
+
+M.Syntax.up = Up()
+M.Syntax.wildcard = Wildcard()
+
+
+function M.Syntax:get_special(comp)
+ return ({['..']=M.Syntax.up, ['*']=M.Syntax.wildcard})[comp]
+end
+
+
+function M.Syntax:is_absolute(path) return path:sub(1, 1) == '/' end
+
+
+function M.Syntax:escape(comp)
+ if type(comp) == 'table' then
+ if object.isinstance(object.toinstance(comp), M.Special) then
+ return comp:tostring()
+ end
+ end
+ if type(comp) == 'number' then return tostring(comp) end
+ local res = comp:gsub('([\\/])', '\\%1')
+ return (self:get_special(res) or tonumber(res)) and '\\'..res or res
+end
+
+
+function M.Syntax:rawjoin(p1, p2, ...)
+ if not p2 then return p1 end
+ if not self:is_absolute(p2) then p2 = '/'..p2 end
+ return self:rawjoin((p1 == '/' and '' or p1)..p2, ...)
+end
+
+function M.Syntax:join(parent, ...)
+ local args = map(function(c) return self:escape(c) end, {...})
+ if parent > '' then table.insert(args, 1, parent) end
+ return self:rawjoin(table.unpack(args))
+end
+
+
+function M.Syntax:split(path)
+ local res = {}
+ local comp = ''
+ local escaped
+
+ local function merge(s)
+ if s > '' then
+ table.insert(
+ res, not escaped and (self:get_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.Syntax:is_unique(path)
+ for _, comp in ipairs(self:split(path)) do
+ if comp == self.wildcard then return false end
+ end
+ return true
+end
+
+function M.Syntax:is_subordinate(p1, p2)
+ p1 = self:split(p1)
+ for i, comp in ipairs(self:split(p2)) do
+ if p1[i] ~= comp then return false end
+ end
+ return true
+end
+
+
+function M.Syntax:to_absolute(path, base)
+ if not self:is_absolute(path) then
+ path = base..(base ~= '/' and '/' or '')..path
+ end
+ local comps = self:split(path)
+ local i = 1
+ while i <= #comps do
+ if comps[i] == self.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 self:join('/', table.unpack(comps))
+end
+
+
+function M.Syntax:parent(path)
+ local comps = self:split(path)
+ table.remove(comps)
+ return self:join('/', table.unpack(comps))
+end
+
+function M.Syntax:name(path)
+ local comps = self:split(path)
+ return comps[#comps]
+end
+
+
+function M.Syntax:export(mod)
+ if not mod then mod = {} end
+ for k, v in pairs(M.Syntax) do
+ if k ~= 'export' then
+ mod[k] = type(v) == 'function' and function(...)
+ return v(self, ...)
+ end or v
+ end
+ end
+ return mod
+end
+
+
+return M