diff options
-rw-r--r-- | luaextra-aux.lua | 38 | ||||
-rw-r--r-- | luaextra-dimen.lua | 20 | ||||
-rw-r--r-- | luaextra-dir.lua | 8 | ||||
-rw-r--r-- | luaextra-file.lua | 79 | ||||
-rw-r--r-- | luaextra-lpeg.lua | 120 | ||||
-rw-r--r-- | luaextra-os.lua | 217 | ||||
-rw-r--r-- | luaextra-table.lua | 3 | ||||
-rw-r--r-- | luaextra-url.lua | 40 |
8 files changed, 367 insertions, 158 deletions
diff --git a/luaextra-aux.lua b/luaextra-aux.lua index 1ff5c08..7950a03 100644 --- a/luaextra-aux.lua +++ b/luaextra-aux.lua @@ -6,19 +6,30 @@ if not modules then modules = { } end modules ['l-aux'] = { license = "see context related readme files" } +-- for inline, no store split : for s in string.gmatch(str,",* *([^,]+)") do .. end + aux = aux or { } local concat, format, gmatch = table.concat, string.format, string.gmatch local tostring, type = tostring, type local lpegmatch = lpeg.match +local P, R, V = lpeg.P, lpeg.R, lpeg.V + +local escape, left, right = P("\\"), P('{'), P('}') + +lpeg.patterns.balanced = P { + [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0, + [2] = left * V(1) * right +} + local space = lpeg.P(' ') local equal = lpeg.P("=") local comma = lpeg.P(",") local lbrace = lpeg.P("{") local rbrace = lpeg.P("}") local nobrace = 1 - (lbrace+rbrace) -local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace } +local nested = lpeg.P { lbrace * (nobrace + lpeg.V(1))^0 * rbrace } local spaces = space^0 local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0) @@ -98,6 +109,8 @@ local pattern = lpeg.Ct(value*(separator*value)^0) aux.settings_to_array_pattern = pattern +-- we could use a weak table as cache + function aux.settings_to_array(str) if not str or str == "" then return { } @@ -182,21 +195,14 @@ end -- temporary here -local digit = lpeg.R("09") -local period = lpeg.P(".") -local zero = lpeg.P("0") - ---~ local finish = lpeg.P(-1) ---~ local nodigit = (1-digit) + finish ---~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000 ---~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100 - +local digit = lpeg.R("09") +local period = lpeg.P(".") +local zero = lpeg.P("0") local trailingzeros = zero^0 * -digit -- suggested by Roberto R -local case_1 = period * trailingzeros / "" -local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") - -local number = digit^1 * (case_1 + case_2) -local stripper = lpeg.Cs((number + 1)^0) +local case_1 = period * trailingzeros / "" +local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "") +local number = digit^1 * (case_1 + case_2) +local stripper = lpeg.Cs((number + 1)^0) --~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100" --~ collectgarbage("collect") @@ -205,6 +211,8 @@ local stripper = lpeg.Cs((number + 1)^0) --~ lpegmatch(stripper,str) --~ print(#str, os.clock()-ts, lpegmatch(stripper,sample)) +lpeg.patterns.strip_zeros = stripper + function aux.strip_zeros(str) return lpegmatch(stripper,str) end diff --git a/luaextra-dimen.lua b/luaextra-dimen.lua index e15e294..a8faa27 100644 --- a/luaextra-dimen.lua +++ b/luaextra-dimen.lua @@ -16,7 +16,7 @@ table.</p> --ldx]]-- local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable -local lpegmatch = lpeg.match +local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match number = number or { } @@ -100,6 +100,7 @@ end <p>We collect a bunch of converters in the <type>number</type> namespace.</p> --ldx]]-- +number.maxdimen = 1073741823 number.todimen = todimen number.dimenfactors = dimenfactors @@ -124,10 +125,12 @@ a number and optionally a unit. When no unit is given a constant capture takes place.</p> --ldx]]-- -local amount = (lpeg.S("+-")^0 * lpeg.R("09")^0 * lpeg.P(".")^0 * lpeg.R("09")^0) + lpeg.Cc("0") -local unit = lpeg.R("az")^1 +local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0") +local unit = R("az")^1 -local pattern = amount/tonumber * (unit^1/dimenfactors + lpeg.Cc(1)) -- tonumber is new +local pattern = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new + +lpeg.patterns.dimenpair = pattern --[[ldx-- <p>We use a metatable to intercept errors. When no key is found in @@ -147,11 +150,18 @@ function string:todimen() return self else local value, unit = lpegmatch(pattern,self) - print(value,unit) return value/unit end end +local amount = S("+-")^0 * R("09")^0 * S(".,")^0 * R("09")^0 +local unit = P("pt") + P("cm") + P("mm") + P("sp") + P("bp") + P("in") + + P("pc") + P("dd") + P("cc") + P("nd") + P("nc") + +local pattern = amount * unit + +lpeg.patterns.validdimen = pattern + --[[ldx-- <p>This converter accepts calls like:</p> diff --git a/luaextra-dir.lua b/luaextra-dir.lua index 3760db2..0d08362 100644 --- a/luaextra-dir.lua +++ b/luaextra-dir.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['l-dir'] = { license = "see context related readme files" } +-- dir.expand_name will be merged with cleanpath and collapsepath + local type = type local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub local lpegmatch = lpeg.match @@ -174,7 +176,7 @@ end local make_indeed = true -- false -if string.find(os.getenv("PATH"),";") then +if string.find(os.getenv("PATH"),";") then -- os.type == "windows" function dir.mkdirs(...) local str, pth = "", "" @@ -241,7 +243,7 @@ if string.find(os.getenv("PATH"),";") then --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath local first, nothing, last = match(str,"^(//)(//*)(.*)$") if first then first = lfs.currentdir() .. "/" @@ -323,7 +325,7 @@ else --~ print(dir.mkdirs("///a/b/c")) --~ print(dir.mkdirs("a/bbb//ccc/")) - function dir.expand_name(str) + function dir.expand_name(str) -- will be merged with cleanpath and collapsepath if not find(str,"^/") then str = lfs.currentdir() .. "/" .. str end diff --git a/luaextra-file.lua b/luaextra-file.lua index c95ef65..6f5f5d0 100644 --- a/luaextra-file.lua +++ b/luaextra-file.lua @@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } local concat = table.concat -local find, gmatch, match, gsub, sub = string.find, string.gmatch, string.match, string.gsub, string.sub +local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match function file.removesuffix(filename) @@ -19,7 +19,9 @@ function file.removesuffix(filename) end function file.addsuffix(filename, suffix) - if not find(filename,"%.[%a%d]+$") then + if not suffix or suffix == "" then + return filename + elseif not find(filename,"%.[%a%d]+$") then return filename .. "." .. suffix else return filename @@ -48,14 +50,33 @@ end file.suffix = file.extname ---~ print(file.join("x/","/y")) ---~ print(file.join("http://","/y")) ---~ print(file.join("http://a","/y")) ---~ print(file.join("http:///a","/y")) ---~ print(file.join("//nas-1","/y")) +--~ function file.join(...) +--~ local pth = concat({...},"/") +--~ pth = gsub(pth,"\\","/") +--~ local a, b = match(pth,"^(.*://)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ a, b = match(pth,"^(//)(.*)$") +--~ if a and b then +--~ return a .. gsub(b,"//+","/") +--~ end +--~ return (gsub(pth,"//+","/")) +--~ end + +local trick_1 = char(1) +local trick_2 = "^" .. trick_1 .. "/+" function file.join(...) - local pth = concat({...},"/") + local lst = { ... } + local a, b = lst[1], lst[2] + if a == "" then + lst[1] = trick_1 + elseif b and find(a,"^/+$") and find(b,"^/") then + lst[1] = "" + lst[2] = gsub(b,"^/+","") + end + local pth = concat(lst,"/") pth = gsub(pth,"\\","/") local a, b = match(pth,"^(.*://)(.*)$") if a and b then @@ -65,9 +86,20 @@ function file.join(...) if a and b then return a .. gsub(b,"//+","/") end + pth = gsub(pth,trick_2,"") return (gsub(pth,"//+","/")) end +--~ print(file.join("//","/y")) +--~ print(file.join("/","/y")) +--~ print(file.join("","/y")) +--~ print(file.join("/x/","/y")) +--~ print(file.join("x/","/y")) +--~ print(file.join("http://","/y")) +--~ print(file.join("http://a","/y")) +--~ print(file.join("http:///a","/y")) +--~ print(file.join("//nas-1","/y")) + function file.iswritable(name) local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) return a and sub(a.permissions,2,2) == "w" @@ -106,16 +138,22 @@ function file.join_path(tab) return concat(tab,io.pathseparator) -- can have trailing // end +-- we can hash them weakly + function file.collapse_path(str) - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") + str = gsub(str,"\\","/") + if find(str,"/") then + str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified + str = gsub(str,"/%./","/") + local n, m = 1, 1 + while n > 0 or m > 0 do + str, n = gsub(str,"[^/%.]+/%.%.$","") + str, m = gsub(str,"[^/%.]+/%.%./","") + end + str = gsub(str,"([^/])/$","%1") + -- str = gsub(str,"^%./","") -- ./xx in qualified + str = gsub(str,"/%.$","") end - str = gsub(str,"([^/])/$","%1") - str = gsub(str,"^%./","") - str = gsub(str,"/%.$","") if str == "" then str = "." end return str end @@ -265,3 +303,12 @@ end -- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" } -- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" } -- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" } + +--~ -- todo: +--~ +--~ if os.type == "windows" then +--~ local currentdir = lfs.currentdir +--~ function lfs.currentdir() +--~ return (gsub(currentdir(),"\\","/")) +--~ end +--~ end diff --git a/luaextra-lpeg.lua b/luaextra-lpeg.lua index 9e761e4..2e366a9 100644 --- a/luaextra-lpeg.lua +++ b/luaextra-lpeg.lua @@ -6,55 +6,58 @@ if not modules then modules = { } end modules ['l-lpeg'] = { license = "see context related readme files" } -lpeg = require("lpeg") +local lpeg = require("lpeg") -local P, R, S, Ct, C, Cs, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc -local match = lpeg.match - ---~ l-lpeg.lua : +lpeg.patterns = lpeg.patterns or { } -- so that we can share +local patterns = lpeg.patterns ---~ lpeg.digit = lpeg.R('09')^1 ---~ lpeg.sign = lpeg.S('+-')^1 ---~ lpeg.cardinal = lpeg.P(lpeg.sign^0 * lpeg.digit^1) ---~ lpeg.integer = lpeg.P(lpeg.sign^0 * lpeg.digit^1) ---~ lpeg.float = lpeg.P(lpeg.sign^0 * lpeg.digit^0 * lpeg.P('.') * lpeg.digit^1) ---~ lpeg.number = lpeg.float + lpeg.integer ---~ lpeg.oct = lpeg.P("0") * lpeg.R('07')^1 ---~ lpeg.hex = lpeg.P("0x") * (lpeg.R('09') + lpeg.R('AF'))^1 ---~ lpeg.uppercase = lpeg.P("AZ") ---~ lpeg.lowercase = lpeg.P("az") - ---~ lpeg.eol = lpeg.S('\r\n\f')^1 -- includes formfeed ---~ lpeg.space = lpeg.S(' ')^1 ---~ lpeg.nonspace = lpeg.P(1-lpeg.space)^1 ---~ lpeg.whitespace = lpeg.S(' \r\n\f\t')^1 ---~ lpeg.nonwhitespace = lpeg.P(1-lpeg.whitespace)^1 +local P, R, S, Ct, C, Cs, Cc, V = lpeg.P, lpeg.R, lpeg.S, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.V +local match = lpeg.match -local hash = { } +local digit, sign = R('09'), S('+-') +local cr, lf, crlf = P("\r"), P("\n"), P("\r\n") +local utf8byte = R("\128\191") + +patterns.utf8byte = utf8byte +patterns.utf8one = R("\000\127") +patterns.utf8two = R("\194\223") * utf8byte +patterns.utf8three = R("\224\239") * utf8byte * utf8byte +patterns.utf8four = R("\240\244") * utf8byte * utf8byte * utf8byte + +patterns.digit = digit +patterns.sign = sign +patterns.cardinal = sign^0 * digit^1 +patterns.integer = sign^0 * digit^1 +patterns.float = sign^0 * digit^0 * P('.') * digit^1 +patterns.number = patterns.float + patterns.integer +patterns.oct = P("0") * R("07")^1 +patterns.octal = patterns.oct +patterns.HEX = P("0x") * R("09","AF")^1 +patterns.hex = P("0x") * R("09","af")^1 +patterns.hexadecimal = P("0x") * R("09","AF","af")^1 +patterns.lowercase = R("az") +patterns.uppercase = R("AZ") +patterns.letter = patterns.lowercase + patterns.uppercase +patterns.space = S(" ") +patterns.eol = S("\n\r") +patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto) +patterns.newline = crlf + cr + lf +patterns.nonspace = 1 - patterns.space +patterns.nonspacer = 1 - patterns.spacer +patterns.whitespace = patterns.eol + patterns.spacer +patterns.nonwhitespace = 1 - patterns.whitespace +patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four +patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191') function lpeg.anywhere(pattern) --slightly adapted from website - return P { P(pattern) + 1 * lpeg.V(1) } -end - -function lpeg.startswith(pattern) --slightly adapted - return P(pattern) + return P { P(pattern) + 1 * V(1) } -- why so complex? end function lpeg.splitter(pattern, action) return (((1-P(pattern))^1)/action+1)^0 end --- variant: - ---~ local parser = lpeg.Ct(lpeg.splitat(newline)) - -local crlf = P("\r\n") -local cr = P("\r") -local lf = P("\n") -local space = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto) -local newline = crlf + cr + lf -local spacing = space^0 * newline - +local spacing = patterns.spacer^0 * patterns.newline -- sort of strip local empty = spacing * Cc("") local nonempty = Cs((1-spacing)^1) * spacing^-1 local content = (empty + nonempty)^1 @@ -65,7 +68,7 @@ function string:splitlines() return match(capture,self) end -lpeg.linebyline = content -- better make a sublibrary +patterns.textline = content --~ local p = lpeg.splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more --~ local p = lpeg.splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more @@ -121,45 +124,20 @@ end --~ local p = pp --~ for l=1,#list do --~ if p then ---~ p = p + lpeg.P(list[l]) +--~ p = p + P(list[l]) --~ else ---~ p = lpeg.P(list[l]) +--~ p = P(list[l]) --~ end --~ end --~ return p --~ end --~ from roberto's site: ---~ ---~ -- decode a two-byte UTF-8 sequence ---~ local function f2 (s) ---~ local c1, c2 = string.byte(s, 1, 2) ---~ return c1 * 64 + c2 - 12416 ---~ end ---~ ---~ -- decode a three-byte UTF-8 sequence ---~ local function f3 (s) ---~ local c1, c2, c3 = string.byte(s, 1, 3) ---~ return (c1 * 64 + c2) * 64 + c3 - 925824 ---~ end ---~ ---~ -- decode a four-byte UTF-8 sequence ---~ local function f4 (s) ---~ local c1, c2, c3, c4 = string.byte(s, 1, 4) ---~ return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 ---~ end ---~ ---~ local cont = lpeg.R("\128\191") -- continuation byte ---~ ---~ local utf8 = lpeg.R("\0\127") / string.byte ---~ + lpeg.R("\194\223") * cont / f2 ---~ + lpeg.R("\224\239") * cont * cont / f3 ---~ + lpeg.R("\240\244") * cont * cont * cont / f4 ---~ ---~ local decode_pattern = lpeg.Ct(utf8^0) * -1 - -local cont = R("\128\191") -- continuation byte +local f1 = string.byte -lpeg.utf8 = R("\0\127") + R("\194\223") * cont + R("\224\239") * cont * cont + R("\240\244") * cont * cont * cont +local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end +local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end +local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end +patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4 diff --git a/luaextra-os.lua b/luaextra-os.lua index b60dfb7..4f0c0c1 100644 --- a/luaextra-os.lua +++ b/luaextra-os.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['l-os'] = { -- maybe build io.flush in os.execute -local find, format = string.find, string.format +local find, format, gsub = string.find, string.format, string.gsub local random, ceil = math.random, math.ceil local execute, spawn, exec, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.flush @@ -43,6 +43,12 @@ end os.type = os.type or (io.pathseparator == ";" and "windows") or "unix" os.name = os.name or (os.type == "windows" and "mswin" ) or "linux" +if os.type == "windows" then + os.libsuffix, os.binsuffix = 'dll', 'exe' +else + os.libsuffix, os.binsuffix = 'so', '' +end + function os.launch(str) if os.type == "windows" then os.execute("start " .. str) -- os.spawn ? @@ -51,10 +57,6 @@ function os.launch(str) end end -if not os.setenv then - function os.setenv() return false end -end - if not os.times then -- utime = user time -- stime = system time @@ -86,63 +88,182 @@ end -- no need for function anymore as we have more clever code and helpers now -os.platform = os.name or os.type or "linux" -os.libsuffix = 'so' -os.binsuffix = '' +os.resolvers = os.resolvers or { } -local name = os.name +local resolvers = os.resolvers -if name == "windows" or name == "mswin" or name == "win32" or name == "msdos" or os.type == "windows" then - if os.getenv("PROCESSOR_ARCHITECTURE") == "AMD64" then - os.platform = "mswin-64" - else - os.platform = "mswin" +local osmt = getmetatable(os) or { __index = function(t,k) t[k] = "unset" return "unset" end } +local osix = osmt.__index + +osmt.__index = function(t,k) + return (resolvers[k] or osix)(t,k) +end + +setmetatable(os,osmt) + +if not os.setenv then + + -- we still store them but they won't be seen in + -- child processes although we might pass them some day + -- using command concatination + + local env, getenv = { }, os.getenv + + function os.setenv(k,v) + env[k] = v end - os.libsuffix = 'dll' - os.binsuffix = 'exe' -else - local architecture = os.getenv("HOSTTYPE") or "" - if architecture == "" then - architecture = os.resultof("uname -m") or "" + + function os.getenv(k) + return env[k] or getenv(k) end - if architecture == "" then - local architecture = os.resultof("echo $HOSTTYPE") + +end + +-- we can use HOSTTYPE on some platforms + +local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or "" + +local function guess() + local architecture = os.resultof("uname -m") or "" + if architecture ~= "" then + return architecture + end + architecture = os.getenv("HOSTTYPE") or "" + if architecture ~= "" then + return architecture + end + return os.resultof("echo $HOSTTYPE") or "" +end + +if platform ~= "" then + + os.platform = platform + +elseif os.type == "windows" then + + -- we could set the variable directly, no function needed here + + function os.resolvers.platform(t,k) + local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or "" + if find(architecture,"AMD64") then + platform = "mswin-64" + else + platform = "mswin" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform end - if name == "linux" then + +elseif name == "linux" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" if find(architecture,"x86_64") then - os.platform = "linux-64" + platform = "linux-64" elseif find(architecture,"ppc") then - os.platform = "linux-ppc" + platform = "linux-ppc" else - os.platform = "linux" + platform = "linux" end - elseif name == "macosx" then - if find(architecture,"i386") then - os.platform = "osx-intel" + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + +elseif name == "macosx" then + + --[[ + Identifying the architecture of OSX is quite a mess and this + is the best we can come up with. For some reason $HOSTTYPE is + a kind of pseudo environment variable, not known to the current + environment. And yes, uname cannot be trusted either, so there + is a change that you end up with a 32 bit run on a 64 bit system. + Also, some proper 64 bit intel macs are too cheap (low-end) and + therefore not permitted to run the 64 bit kernel. + ]]-- + + function os.resolvers.platform(t,k) + -- local platform, architecture = "", os.getenv("HOSTTYPE") or "" + -- if architecture == "" then + -- architecture = os.resultof("echo $HOSTTYPE") or "" + -- end + local platform, architecture = "", os.resultof("echo $HOSTTYPE") or "" + if architecture == "" then + -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n") + platform = "osx-intel" + elseif find(architecture,"i386") then + platform = "osx-intel" elseif find(architecture,"x86_64") then - os.platform = "osx-64" + platform = "osx-64" else - os.platform = "osx-ppc" + platform = "osx-ppc" end - elseif name == "sunos" then + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + +elseif name == "sunos" then + + function os.resolvers.platform(t,k) + local platform, architecture = "", os.resultof("uname -m") or "" if find(architecture,"sparc") then - os.platform = "solaris-sparc" + platform = "solaris-sparc" else -- if architecture == 'i86pc' - os.platform = "solaris-intel" + platform = "solaris-intel" end - elseif name == "freebsd" then + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + +elseif name == "freebsd" then + + function os.resolvers.platform(t,k) + local platform, architecture = "", os.resultof("uname -m") or "" if find(architecture,"amd64") then - os.platform = "freebsd-amd64" + platform = "freebsd-amd64" else - os.platform = "freebsd" + platform = "freebsd" end - else - os.platform = 'linux' + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform end + +elseif name == "kfreebsd" then + + function os.resolvers.platform(t,k) + -- we sometims have HOSTTYPE set so let's check that first + local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" + if find(architecture,"x86_64") then + platform = "kfreebsd-64" + else + platform = "kfreebsd-i386" + end + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + +else + + -- platform = "linux" + -- os.setenv("MTX_PLATFORM",platform) + -- os.platform = platform + + function os.resolvers.platform(t,k) + local platform = "linux" + os.setenv("MTX_PLATFORM",platform) + os.platform = platform + return platform + end + end -- beware, we set the randomseed --- -- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the -- version number as well as two reserved bits. All other bits are set using a random or pseudorandom @@ -151,7 +272,6 @@ end -- -- as we don't call this function too often there is not so much risk on repetition - local t = { 8, 9, "a", "b" } function os.uuid() @@ -163,3 +283,18 @@ function os.uuid() random(0xFFFF),random(0xFFFF),random(0xFFFF) ) end + +local d + +function os.timezone(delta) + d = d or tonumber(tonumber(os.date("%H")-os.date("!%H"))) + if delta then + if d > 0 then + return format("+%02i:00",d) + else + return format("-%02i:00",-d) + end + else + return 1 + end +end diff --git a/luaextra-table.lua b/luaextra-table.lua index 70a901e..e8f72ed 100644 --- a/luaextra-table.lua +++ b/luaextra-table.lua @@ -12,6 +12,7 @@ local concat, sort, insert, remove = table.concat, table.sort, table.insert, tab local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match local getmetatable, setmetatable = getmetatable, setmetatable local type, next, tostring, tonumber, ipairs, pairs = type, next, tostring, tonumber, ipairs, pairs +local unpack = unpack or table.unpack function table.strip(tab) local lst = { } @@ -28,7 +29,7 @@ end function table.keys(t) local k = { } - for key,_ in next, t do + for key, _ in next, t do k[#k+1] = key end return k diff --git a/luaextra-url.lua b/luaextra-url.lua index 1d282a1..e3e6f81 100644 --- a/luaextra-url.lua +++ b/luaextra-url.lua @@ -32,7 +32,9 @@ local hexdigit = lpeg.R("09","AF","af") local plus = lpeg.P("+") local escaped = (plus / " ") + (percent * lpeg.C(hexdigit * hexdigit) / tochar) -local scheme = lpeg.Cs((escaped+(1-colon-slash-qmark-hash))^0) * colon + lpeg.Cc("") +-- we assume schemes with more than 1 character (in order to avoid problems with windows disks) + +local scheme = lpeg.Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon + lpeg.Cc("") local authority = slash * slash * lpeg.Cs((escaped+(1- slash-qmark-hash))^0) + lpeg.Cc("") local path = slash * lpeg.Cs((escaped+(1- qmark-hash))^0) + lpeg.Cc("") local query = qmark * lpeg.Cs((escaped+(1- hash))^0) + lpeg.Cc("") @@ -40,22 +42,48 @@ local fragment = hash * lpeg.Cs((escaped+(1- endofstring))^0 local parser = lpeg.Ct(scheme * authority * path * query * fragment) +-- todo: reconsider Ct as we can as well have five return values (saves a table) +-- so we can have two parsers, one with and one without + function url.split(str) return (type(str) == "string" and lpegmatch(parser,str)) or str end +-- todo: cache them + function url.hashed(str) local s = url.split(str) + local somescheme = s[1] ~= "" return { - scheme = (s[1] ~= "" and s[1]) or "file", + scheme = (somescheme and s[1]) or "file", authority = s[2], - path = s[3], - query = s[4], - fragment = s[5], - original = str + path = s[3], + query = s[4], + fragment = s[5], + original = str, + noscheme = not somescheme, } end +function url.hasscheme(str) + return url.split(str)[1] ~= "" +end + +function url.addscheme(str,scheme) + return (url.hasscheme(str) and str) or ((scheme or "file:///") .. str) +end + +function url.construct(hash) + local fullurl = hash.sheme .. "://".. hash.authority .. hash.path + if hash.query then + fullurl = fullurl .. "?".. hash.query + end + if hash.fragment then + fullurl = fullurl .. "?".. hash.fragment + end + return fullurl +end + function url.filename(filename) local t = url.hashed(filename) return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename |