summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lualibs-lpeg.lua5
-rw-r--r--lualibs-os.lua57
-rw-r--r--lualibs-package.lua24
-rw-r--r--lualibs-unicode.lua31
-rw-r--r--lualibs-url.lua16
-rw-r--r--lualibs-util-env.lua1
-rw-r--r--lualibs-util-tab.lua53
7 files changed, 162 insertions, 25 deletions
diff --git a/lualibs-lpeg.lua b/lualibs-lpeg.lua
index cafa18a..58c5524 100644
--- a/lualibs-lpeg.lua
+++ b/lualibs-lpeg.lua
@@ -82,7 +82,6 @@ setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
lpeg.patterns = lpeg.patterns or { } -- so that we can share
local patterns = lpeg.patterns
-
local anything = P(1)
local endofstring = P(-1)
local alwaysmatched = P(true)
@@ -120,6 +119,9 @@ local utfbom = utfbom_32_be + utfbom_32_le
local utftype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ utfbom_8 * Cc("utf-8") + alwaysmatched * Cc("utf-8") -- assume utf8
+local utfstricttype = utfbom_32_be * Cc("utf-32-be") + utfbom_32_le * Cc("utf-32-le")
+ + utfbom_16_be * Cc("utf-16-be") + utfbom_16_le * Cc("utf-16-le")
+ + utfbom_8 * Cc("utf-8")
local utfoffset = utfbom_32_be * Cc(4) + utfbom_32_le * Cc(4)
+ utfbom_16_be * Cc(2) + utfbom_16_le * Cc(2)
+ utfbom_8 * Cc(3) + Cc(0)
@@ -141,6 +143,7 @@ patterns.utf8three = R("\224\239") * utf8next * utf8next
patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
patterns.utfbom = utfbom
patterns.utftype = utftype
+patterns.utfstricttype = utfstricttype
patterns.utfoffset = utfoffset
local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
diff --git a/lualibs-os.lua b/lualibs-os.lua
index 8bfcf78..7f3fd7c 100644
--- a/lualibs-os.lua
+++ b/lualibs-os.lua
@@ -492,3 +492,60 @@ end
-- print(os.which("inkscape"))
-- print(os.which("gs.exe"))
-- print(os.which("ps2pdf"))
+
+-- These are moved from core-con.lua (as I needed them elsewhere).
+
+local function isleapyear(year)
+ return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0))
+end
+
+os.isleapyear = isleapyear
+
+-- nicer:
+--
+-- local days = {
+-- [false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+-- [true] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+-- }
+--
+-- local function nofdays(year,month)
+-- return days[isleapyear(year)][month]
+-- return month == 2 and isleapyear(year) and 29 or days[month]
+-- end
+--
+-- more efficient:
+
+local days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+
+local function nofdays(year,month)
+ if not month then
+ return isleapyear(year) and 365 or 364
+ else
+ return month == 2 and isleapyear(year) and 29 or days[month]
+ end
+end
+
+os.nofdays = nofdays
+
+function os.weekday(day,month,year)
+ return date("%w",time { year = year, month = month, day = day }) + 1
+end
+
+function os.validdate(year,month,day)
+ -- we assume that all three values are set
+ -- year is always ok, even if lua has a 1970 time limit
+ if month < 1 then
+ month = 1
+ elseif month > 12 then
+ month = 12
+ end
+ if day < 1 then
+ day = 1
+ else
+ local max = nofdays(year,month)
+ if day > max then
+ day = max
+ end
+ end
+ return year, month, day
+end
diff --git a/lualibs-package.lua b/lualibs-package.lua
index 579fd39..0dbff7c 100644
--- a/lualibs-package.lua
+++ b/lualibs-package.lua
@@ -17,7 +17,7 @@ if not modules then modules = { } end modules ['l-package'] = {
-- -- local mysql = require("luasql.mysql")
local type = type
-local gsub, format = string.gsub, string.format
+local gsub, format, find = string.gsub, string.format, string.find
local P, S, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.Cs, lpeg.match
@@ -68,6 +68,7 @@ local helpers = package.helpers or {
sequence = {
"already loaded",
"preload table",
+ "qualified path", -- beware, lua itself doesn't handle qualified paths (prepends ./)
"lua extra list",
"lib extra list",
"path specification",
@@ -243,6 +244,23 @@ end
helpers.loadedbypath = loadedbypath
+local function loadedbyname(name,rawname)
+ if find(name,"^/") or find(name,"^[a-zA-Z]:/") then
+ local trace=helpers.trace
+ if trace then
+ helpers.report("qualified name, identifying '%s'",what,name)
+ end
+ if isreadable(name) then
+ if trace then
+ helpers.report("qualified name, '%s' found",what,name)
+ end
+ return loadfile(name)
+ end
+ end
+end
+
+helpers.loadedbyname = loadedbyname
+
methods["already loaded"] = function(name)
return package.loaded[name]
end
@@ -251,6 +269,10 @@ methods["preload table"] = function(name)
return builtin["preload table"](name)
end
+methods["qualified path"]=function(name)
+ return loadedbyname(addsuffix(lualibfile(name),"lua"),name)
+end
+
methods["lua extra list"] = function(name)
return loadedbypath(addsuffix(lualibfile(name),"lua" ),name,getextraluapaths(),false,"lua")
end
diff --git a/lualibs-unicode.lua b/lualibs-unicode.lua
index 3ce5bd3..7ada394 100644
--- a/lualibs-unicode.lua
+++ b/lualibs-unicode.lua
@@ -38,13 +38,14 @@ local replacer = lpeg.replacer
local utfvalues = utf.values
local utfgmatch = utf.gmatch -- not always present
-local p_utftype = patterns.utftype
-local p_utfoffset = patterns.utfoffset
-local p_utf8char = patterns.utf8char
-local p_utf8byte = patterns.utf8byte
-local p_utfbom = patterns.utfbom
-local p_newline = patterns.newline
-local p_whitespace = patterns.whitespace
+local p_utftype = patterns.utftype
+local p_utfstricttype = patterns.utfstricttype
+local p_utfoffset = patterns.utfoffset
+local p_utf8char = patterns.utf8char
+local p_utf8byte = patterns.utf8byte
+local p_utfbom = patterns.utfbom
+local p_newline = patterns.newline
+local p_whitespace = patterns.whitespace
if not unicode then
@@ -976,6 +977,22 @@ function utf.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+function utf.toeight(str)
+ if not str then
+ return nil
+ end
+ local utftype = lpegmatch(p_utfstricttype,str)
+ if utftype == "utf-8" then
+ return sub(str,4)
+ elseif utftype == "utf-16-le" then
+ return utf16_to_utf8_le(str)
+ elseif utftype == "utf-16-be" then
+ return utf16_to_utf8_ne(str)
+ else
+ return str
+ end
+end
+
--
local p_nany = p_utf8char / ""
diff --git a/lualibs-url.lua b/lualibs-url.lua
index 4624a05..7b7910f 100644
--- a/lualibs-url.lua
+++ b/lualibs-url.lua
@@ -79,12 +79,18 @@ setmetatable(escapes, { __index = function(t,k)
return v
end })
-local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
-local unescaper = Cs((escapedchar + 1)^0)
+local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
+local unescaper = Cs((escapedchar + 1)^0)
+local getcleaner = Cs((P("+++") / "%%2B" + P("+") / "%%20" + P(1))^1)
-lpegpatterns.urlunescaped = escapedchar
-lpegpatterns.urlescaper = escaper
-lpegpatterns.urlunescaper = unescaper
+lpegpatterns.urlunescaped = escapedchar
+lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaper = unescaper
+lpegpatterns.urlgetcleaner = getcleaner
+
+function url.unescapeget(str)
+ return lpegmatch(getcleaner,str)
+end
-- 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
diff --git a/lualibs-util-env.lua b/lualibs-util-env.lua
index f4f3ef6..1184c1d 100644
--- a/lualibs-util-env.lua
+++ b/lualibs-util-env.lua
@@ -57,6 +57,7 @@ environment.basicengines = basicengines
-- instead we could set ranges
if not arg then
+ environment.used_as_library = true
-- used as library
elseif luaengines[file.removesuffix(arg[-1])] then
-- arg[-1] = arg[0]
diff --git a/lualibs-util-tab.lua b/lualibs-util-tab.lua
index f18c719..ae44269 100644
--- a/lualibs-util-tab.lua
+++ b/lualibs-util-tab.lua
@@ -10,13 +10,14 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch, gsub = string.format, string.gmatch, string.gsub
+local format, gmatch, gsub, sub = string.format, string.gmatch, string.gsub, string.sub
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
local type, next, rawset, tonumber, tostring, load, select = type, next, rawset, tonumber, tostring, load, select
local lpegmatch, P, Cs, Cc = lpeg.match, lpeg.P, lpeg.Cs, lpeg.Cc
local sortedkeys, sortedpairs = table.sortedkeys, table.sortedpairs
local formatters = string.formatters
+local utftoeight = utf.toeight
local splitter = lpeg.tsplitat(".")
@@ -300,11 +301,20 @@ local f_hashed_number = formatters["[%q]=%s,"]
local f_hashed_boolean = formatters["[%q]=%l,"]
local f_hashed_table = formatters["[%q]="]
-local f_indexed_string = formatters["%q,"]
-local f_indexed_number = formatters["%s,"]
-local f_indexed_boolean = formatters["%l,"]
+local f_indexed_string = formatters["[%s]=%q,"]
+local f_indexed_number = formatters["[%s]=%s,"]
+local f_indexed_boolean = formatters["[%s]=%l,"]
+local f_indexed_table = formatters["[%s]="]
-function table.fastserialize(t,prefix) -- so prefix should contain the = | not sorted
+local f_ordered_string = formatters["%q,"]
+local f_ordered_number = formatters["%s,"]
+local f_ordered_boolean = formatters["%l,"]
+
+function table.fastserialize(t,prefix)
+
+ -- prefix should contain the =
+ -- not sorted
+ -- only number and string indices (currently)
local r = { prefix or "return" }
local m = 1
@@ -314,21 +324,37 @@ function table.fastserialize(t,prefix) -- so prefix should contain the = | not s
m = m + 1
r[m] = "{"
if n > 0 then
- for i=1,n do
+ for i=0,n do
local v = t[i]
local tv = type(v)
if tv == "string" then
- m = m + 1 r[m] = f_indexed_string(v)
+ m = m + 1 r[m] = f_ordered_string(v)
elseif tv == "number" then
- m = m + 1 r[m] = f_indexed_number(v)
+ m = m + 1 r[m] = f_ordered_number(v)
elseif tv == "table" then
fastserialize(v)
elseif tv == "boolean" then
- m = m + 1 r[m] = f_indexed_boolean(v)
+ m = m + 1 r[m] = f_ordered_boolean(v)
end
end
- else
- for k, v in next, t do
+ end
+ for k, v in next, t do
+ local tk = type(k)
+ if tk == "number" then
+ if k > n or k < 0 then
+ local tv = type(v)
+ if tv == "string" then
+ m = m + 1 r[m] = f_indexed_string(k,v)
+ elseif tv == "number" then
+ m = m + 1 r[m] = f_indexed_number(k,v)
+ elseif tv == "table" then
+ m = m + 1 r[m] = f_indexed_table(k)
+ fastserialize(v)
+ elseif tv == "boolean" then
+ m = m + 1 r[m] = f_indexed_boolean(k,v)
+ end
+ end
+ else
local tv = type(v)
if tv == "string" then
m = m + 1 r[m] = f_hashed_string(k,v)
@@ -375,6 +401,7 @@ function table.load(filename,loader)
if filename then
local t = (loader or io.loaddata)(filename)
if t and t ~= "" then
+ local t = utftoeight(t)
t = load(t)
if type(t) == "function" then
t = t()
@@ -518,6 +545,10 @@ local spaces = utilities.strings.newrepeater(" ")
local serialize = table.serialize -- the extensive one, the one we started with
+-- there is still room for optimization: index run, key run, but i need to check with the
+-- latest lua for the value of #n (with holes) .. anyway for tracing purposes we want
+-- indices / keys being sorted, so it will never be real fast
+
function table.serialize(root,name,specification)
if type(specification) == "table" then