summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Pégourié-Gonnard <mpg@elzevir.fr>2010-03-28 14:34:44 +0200
committerManuel Pégourié-Gonnard <mpg@elzevir.fr>2010-03-28 14:34:44 +0200
commit0bb6d1e8d28f914398d3b3de15cf5317f480d02a (patch)
treea222ca028b0f3bec9f4057424623323602174c29
parent7047b46b6fe6dead388c8427a7510710f920b617 (diff)
parent22fa4cc9381179fdd43ca8a251cb49dd2703079d (diff)
downloadlualibs-0bb6d1e8d28f914398d3b3de15cf5317f480d02a.tar.gz
Merge remote branch 'github/master'
-rw-r--r--luaextra-aux.lua38
-rw-r--r--luaextra-dimen.lua20
-rw-r--r--luaextra-dir.lua8
-rw-r--r--luaextra-file.lua79
-rw-r--r--luaextra-lpeg.lua120
-rw-r--r--luaextra-os.lua217
-rw-r--r--luaextra-table.lua3
-rw-r--r--luaextra-url.lua40
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