diff options
Diffstat (limited to 'macros/luatex/generic/lualibs/lualibs-extended-merged.lua')
-rw-r--r-- | macros/luatex/generic/lualibs/lualibs-extended-merged.lua | 1173 |
1 files changed, 1154 insertions, 19 deletions
diff --git a/macros/luatex/generic/lualibs/lualibs-extended-merged.lua b/macros/luatex/generic/lualibs/lualibs-extended-merged.lua index 9cd4487bf2..08428c51ac 100644 --- a/macros/luatex/generic/lualibs/lualibs-extended-merged.lua +++ b/macros/luatex/generic/lualibs/lualibs-extended-merged.lua @@ -1,6 +1,511 @@ -- merged file : lualibs-extended-merged.lua -- parent file : lualibs-extended.lua --- merge date : 2021-05-20 23:14 +-- merge date : 2022-10-04 17:16 + +do -- begin closure to overcome local limits and interference + +if not modules then modules={} end modules ['util-sac']={ + version=1.001, + optimize=true, + comment="companion to luat-lib.mkiv", + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files" +} +local byte,sub=string.byte,string.sub +local tonumber=tonumber +utilities=utilities or {} +local streams={} +utilities.streams=streams +function streams.open(filename,zerobased) + local f=filename and io.loaddata(filename) + if f then + return { f,1,#f,zerobased or false } + end +end +function streams.openstring(f,zerobased) + if f then + return { f,1,#f,zerobased or false } + end +end +function streams.getstring(f) + if f then + return f[1] + end +end +function streams.close() +end +function streams.size(f) + return f and f[3] or 0 +end +streams.getsize=streams.size +function streams.setposition(f,i) + if f[4] then + if i<=0 then + f[2]=1 + else + f[2]=i+1 + end + else + if i<=1 then + f[2]=1 + else + f[2]=i + end + end +end +function streams.getposition(f) + if f[4] then + return f[2]-1 + else + return f[2] + end +end +function streams.look(f,n,chars) + local b=f[2] + local e=b+n-1 + if chars then + return sub(f[1],b,e) + else + return byte(f[1],b,e) + end +end +function streams.skip(f,n) + f[2]=f[2]+n +end +function streams.readbyte(f) + local i=f[2] + f[2]=i+1 + return byte(f[1],i) +end +function streams.readbytes(f,n) + local i=f[2] + local j=i+n + f[2]=j + return byte(f[1],i,j-1) +end +function streams.readbytetable(f,n) + local i=f[2] + local j=i+n + f[2]=j + return { byte(f[1],i,j-1) } +end +function streams.skipbytes(f,n) + f[2]=f[2]+n +end +function streams.readchar(f) + local i=f[2] + f[2]=i+1 + return sub(f[1],i,i) +end +function streams.readstring(f,n) + local i=f[2] + local j=i+n + f[2]=j + return sub(f[1],i,j-1) +end +function streams.readinteger1(f) + local i=f[2] + f[2]=i+1 + local n=byte(f[1],i) + if n>=0x80 then + return n-0x100 + else + return n + end +end +streams.readcardinal1=streams.readbyte +streams.readcardinal=streams.readcardinal1 +streams.readinteger=streams.readinteger1 +function streams.readcardinal2(f) + local i=f[2] + local j=i+1 + f[2]=j+1 + local a,b=byte(f[1],i,j) + return 0x100*a+b +end +function streams.readcardinal2le(f) + local i=f[2] + local j=i+1 + f[2]=j+1 + local b,a=byte(f[1],i,j) + return 0x100*a+b +end +function streams.readinteger2(f) + local i=f[2] + local j=i+1 + f[2]=j+1 + local a,b=byte(f[1],i,j) + if a>=0x80 then + return 0x100*a+b-0x10000 + else + return 0x100*a+b + end +end +function streams.readinteger2le(f) + local i=f[2] + local j=i+1 + f[2]=j+1 + local b,a=byte(f[1],i,j) + if a>=0x80 then + return 0x100*a+b-0x10000 + else + return 0x100*a+b + end +end +function streams.readcardinal3(f) + local i=f[2] + local j=i+2 + f[2]=j+1 + local a,b,c=byte(f[1],i,j) + return 0x10000*a+0x100*b+c +end +function streams.readcardinal3le(f) + local i=f[2] + local j=i+2 + f[2]=j+1 + local c,b,a=byte(f[1],i,j) + return 0x10000*a+0x100*b+c +end +function streams.readinteger3(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local a,b,c=byte(f[1],i,j) + if a>=0x80 then + return 0x10000*a+0x100*b+c-0x1000000 + else + return 0x10000*a+0x100*b+c + end +end +function streams.readinteger3le(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local c,b,a=byte(f[1],i,j) + if a>=0x80 then + return 0x10000*a+0x100*b+c-0x1000000 + else + return 0x10000*a+0x100*b+c + end +end +function streams.readcardinal4(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local a,b,c,d=byte(f[1],i,j) + return 0x1000000*a+0x10000*b+0x100*c+d +end +function streams.readcardinal4le(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local d,c,b,a=byte(f[1],i,j) + return 0x1000000*a+0x10000*b+0x100*c+d +end +function streams.readinteger4(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local a,b,c,d=byte(f[1],i,j) + if a>=0x80 then + return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 + else + return 0x1000000*a+0x10000*b+0x100*c+d + end +end +function streams.readinteger4le(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local d,c,b,a=byte(f[1],i,j) + if a>=0x80 then + return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 + else + return 0x1000000*a+0x10000*b+0x100*c+d + end +end +function streams.readfixed2(f) + local i=f[2] + local j=i+1 + f[2]=j+1 + local n1,n2=byte(f[1],i,j) + if n1>=0x80 then + n1=n1-0x100 + end + return n1+n2/0xFF +end +function streams.readfixed4(f) + local i=f[2] + local j=i+3 + f[2]=j+1 + local a,b,c,d=byte(f[1],i,j) + local n1=0x100*a+b + local n2=0x100*c+d + if n1>=0x8000 then + n1=n1-0x10000 + end + return n1+n2/0xFFFF +end +if bit32 then + local extract=bit32.extract + local band=bit32.band + function streams.read2dot14(f) + local i=f[2] + local j=i+1 + f[2]=j+1 + local a,b=byte(f[1],i,j) + if a>=0x80 then + local n=-(0x100*a+b) + return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0)) + else + local n=0x100*a+b + return (extract(n,14,2)+(band(n,0x3FFF)/16384.0)) + end + end +end +function streams.skipshort(f,n) + f[2]=f[2]+2*(n or 1) +end +function streams.skiplong(f,n) + f[2]=f[2]+4*(n or 1) +end +if sio and sio.readcardinal2 then + local readcardinal1=sio.readcardinal1 + local readcardinal2=sio.readcardinal2 + local readcardinal3=sio.readcardinal3 + local readcardinal4=sio.readcardinal4 + local readinteger1=sio.readinteger1 + local readinteger2=sio.readinteger2 + local readinteger3=sio.readinteger3 + local readinteger4=sio.readinteger4 + local readfixed2=sio.readfixed2 + local readfixed4=sio.readfixed4 + local read2dot14=sio.read2dot14 + local readbytes=sio.readbytes + local readbytetable=sio.readbytetable + function streams.readcardinal1(f) + local i=f[2] + f[2]=i+1 + return readcardinal1(f[1],i) + end + function streams.readcardinal2(f) + local i=f[2] + f[2]=i+2 + return readcardinal2(f[1],i) + end + function streams.readcardinal3(f) + local i=f[2] + f[2]=i+3 + return readcardinal3(f[1],i) + end + function streams.readcardinal4(f) + local i=f[2] + f[2]=i+4 + return readcardinal4(f[1],i) + end + function streams.readinteger1(f) + local i=f[2] + f[2]=i+1 + return readinteger1(f[1],i) + end + function streams.readinteger2(f) + local i=f[2] + f[2]=i+2 + return readinteger2(f[1],i) + end + function streams.readinteger3(f) + local i=f[2] + f[2]=i+3 + return readinteger3(f[1],i) + end + function streams.readinteger4(f) + local i=f[2] + f[2]=i+4 + return readinteger4(f[1],i) + end + function streams.readfixed2(f) + local i=f[2] + f[2]=i+2 + return readfixed2(f[1],i) + end + function streams.readfixed4(f) + local i=f[2] + f[2]=i+4 + return readfixed4(f[1],i) + end + function streams.read2dot14(f) + local i=f[2] + f[2]=i+2 + return read2dot14(f[1],i) + end + function streams.readbytes(f,n) + local i=f[2] + local s=f[3] + local p=i+n + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readbytes(f[1],i,n) + end + function streams.readbytetable(f,n) + local i=f[2] + local s=f[3] + local p=i+n + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readbytetable(f[1],i,n) + end + streams.readbyte=streams.readcardinal1 + streams.readsignedbyte=streams.readinteger1 + streams.readcardinal=streams.readcardinal1 + streams.readinteger=streams.readinteger1 +end +if sio and sio.readcardinaltable then + local readcardinaltable=sio.readcardinaltable + local readintegertable=sio.readintegertable + function utilities.streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readcardinaltable(f[1],i,n,b) + end + function utilities.streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + return readintegertable(f[1],i,n,b) + end +else + local readcardinal1=streams.readcardinal1 + local readcardinal2=streams.readcardinal2 + local readcardinal3=streams.readcardinal3 + local readcardinal4=streams.readcardinal4 + function streams.readcardinaltable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + local t={} + if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end + return t + end + local readinteger1=streams.readinteger1 + local readinteger2=streams.readinteger2 + local readinteger3=streams.readinteger3 + local readinteger4=streams.readinteger4 + function streams.readintegertable(f,n,b) + local i=f[2] + local s=f[3] + local p=i+n*b + if p>s then + f[2]=s+1 + else + f[2]=p + end + local t={} + if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end + elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end + elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end + elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end + return t + end +end +do + local files=utilities.files + if files then + local openfile=files.open + local openstream=streams.open + local openstring=streams.openstring + local setmetatable=setmetatable + function io.newreader(str,method) + local f,m + if method=="string" then + f=openstring(str,true) + m=streams + elseif method=="stream" then + f=openstream(str,true) + m=streams + else + f=openfile(str,"rb") + m=files + end + if f then + local t={} + setmetatable(t,{ + __index=function(t,k) + local r=m[k] + if k=="close" then + if f then + m.close(f) + f=nil + end + return function() end + elseif r then + local v=function(_,a,b) return r(f,a,b) end + t[k]=v + return v + else + print("unknown key",k) + end + end + } ) + return t + end + end + end +end +if bit32 and not streams.tocardinal1 then + local extract=bit32.extract + local char=string.char + streams.tocardinal1=char + function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end + function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + streams.tocardinal1le=char + function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end + function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end + function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end +end +if not streams.readcstring then + local readchar=streams.readchar + local concat=table.concat + function streams.readcstring(f) + local t={} + while true do + local c=readchar(f) + if c and c~="\0" then + t[#t+1]=c + else + return concat(t) + end + end + end +end + +end -- closure do -- begin closure to overcome local limits and interference @@ -14,12 +519,13 @@ if not modules then modules={} end modules ['util-str']={ utilities=utilities or {} utilities.strings=utilities.strings or {} local strings=utilities.strings -local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find +local format,gsub,rep,sub,find,char=string.format,string.gsub,string.rep,string.sub,string.find,string.char local load,dump=load,string.dump local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable local unpack,concat=table.unpack,table.concat local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc local patterns,lpegmatch=lpeg.patterns,lpeg.match +local tsplitat=lpeg.tsplitat local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len local loadstripped=function(str,shortcuts) if shortcuts then @@ -373,6 +879,14 @@ patterns.escapedquotes=pattern function string.escapedquotes(s) return lpegmatch(pattern,s) end +local pattern=(1-P("\\"))^1;pattern=Cs ( + pattern*((P("\\")/""*(digit^-3/function(s) return char(tonumber(s)) end))+pattern )^1 +) +patterns.unescapedquotes=pattern +function string.unescapedquotes(s) + return lpegmatch(pattern,s) or s +end +string.texnewlines=lpeg.replacer(patterns.newline,"\r",true) local preamble="" local environment={ global=global or _G, @@ -908,7 +1422,6 @@ function number.to16dot16(n) return f_16_16(n/65536.0) end if not string.explode then - local tsplitat=lpeg.tsplitat local p_utf=patterns.utf8character local p_check=C(p_utf)*(P("+")*Cc(true))^0 local p_split=Ct(C(p_utf)^0) @@ -928,6 +1441,20 @@ if not string.explode then end end end +do + local p_whitespace=patterns.whitespace^1 + local cache=setmetatable({},{ __index=function(t,k) + local p=tsplitat(p_whitespace*P(k)*p_whitespace) + local v=function(s) + return lpegmatch(p,s) + end + t[k]=v + return v + end }) + function string.wordsplitter(s) + return cache[s] + end +end end -- closure @@ -1552,9 +2079,6 @@ if JITSUPPORTED then return concat(fastserialize(t,true)) end else - local f_v=formatters["[%q]=%q,"] - local f_t=formatters["[%q]="] - local f_q=formatters["%q,"] function table.fastserialize(t,prefix) local r={ type(prefix)=="string" and prefix or "return" } local m=1 @@ -1963,6 +2487,21 @@ function table.ordered(t) return function() end end end +function combine(target,source) + if target then + for k,v in next,source do + if type(v)=="table" then + target[k]=combine(target[k],source[k]) + else + target[k]=v + end + end + return target + else + return source + end +end +table.combine=combine end -- closure @@ -2181,8 +2720,8 @@ local noparent=1-(lparent+rparent) local nobracket=1-(lbracket+rbracket) local escape,left,right=P("\\"),P('{'),P('}') lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right + ((escape*(left+right))+(1-(left+right))+V(2))^0, + left*V(1)*right } local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } local nestedparents=P { lparent*(noparent+V(1))^0*rparent } @@ -2190,11 +2729,12 @@ local nestedbrackets=P { lbracket*(nobracket+V(1))^0*rbracket } local spaces=space^0 local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/"")) local content=(1-endofstring)^0 -lpegpatterns.nestedbraces=nestedbraces -lpegpatterns.nestedparents=nestedparents -lpegpatterns.nested=nestedbraces -lpegpatterns.argument=argument -lpegpatterns.content=content +lpegpatterns.nestedbraces=nestedbraces +lpegpatterns.nestedparents=nestedparents +lpegpatterns.nestedbrackets=nestedbrackets +lpegpatterns.nested=nestedbraces +lpegpatterns.argument=argument +lpegpatterns.content=content local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0) local key=C((1-equal-comma)^1) local pattern_a=(space+comma)^0*(key*equal*value+key*C("")) @@ -2600,15 +3140,24 @@ local function ranger(first,last,n,action) action(first) end end -local cardinal=lpegpatterns.cardinal/tonumber +local cardinal=(lpegpatterns.hexadecimal+lpegpatterns.cardinal)/tonumber local spacers=lpegpatterns.spacer^0 local endofstring=lpegpatterns.endofstring local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1 local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring function parsers.stepper(str,n,action) + local ts=type(str) if type(n)=="function" then - lpegmatch(stepper,str,1,false,n or print) - else + if ts=="number" then + n(str) + elseif ts=="table" then + for i=1,#str do + n(str[i]) + end + else + lpegmatch(stepper,str,1,false,n or print) + end + elseif ts=="string" then lpegmatch(stepper,str,1,n,action or print) end end @@ -2626,7 +3175,7 @@ local cache={} local spaces=lpegpatterns.space^0 local dummy=function() end setmetatableindex(cache,function(t,k) - local separator=P(k) + local separator=S(k) local value=(1-separator)^0 local pattern=spaces*C(value)*separator^0*Cp() t[k]=pattern @@ -2706,8 +3255,11 @@ local p_year=lpegpatterns.digit^4/tonumber local pattern=Cf(Ct("")*( (Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("day")*cardinal) )+(Cg(Cc("day")*cardinal)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year) + )+(Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal) + )+(Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year) ) - )*P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1 + )*( + P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1+P(-1) ) ,rawset) lpegpatterns.splittime=pattern function parsers.totime(str) @@ -2914,6 +3466,9 @@ if not modules then modules={} end modules ['util-jsn']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } +if utilities and utilities.json then + return json +end local P,V,R,S,C,Cc,Cs,Ct,Cf,Cg=lpeg.P,lpeg.V,lpeg.R,lpeg.S,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cf,lpeg.Cg local lpegmatch=lpeg.match local format,gsub=string.format,string.gsub @@ -3118,6 +3673,8 @@ do k=lpegmatch(escaper,k) or k v=lpegmatch(escaper,v) or v n=n+1 t[n]=f_key_val_str(depth,k,v) + elseif i>1 then + n=n-1 end elseif tv=="table" then local l=#v @@ -3133,6 +3690,8 @@ do end elseif next(v) then tojsonpp(v,k,depth,level+1,0) + elseif i>1 then + n=n-1 end elseif tv=="boolean" then if tk=="number" then @@ -3150,6 +3709,8 @@ do else t[n]=f_key_val_nop(depth,k) end + elseif i>1 then + n=n-1 end else if tk=="number" then @@ -3159,6 +3720,8 @@ do k=lpegmatch(escaper,k) or k n=n+1 t[n]=f_key_val_null(depth,k) + elseif i>1 then + n=n-1 end end end @@ -3260,7 +3823,6 @@ do return jsontostring(value,true) end end -return json end -- closure @@ -3990,6 +4552,22 @@ local function showtraceback(rep) end end debugger.showtraceback=showtraceback +if luac then + local show,dump=luac.print,string.dump + function luac.inspect(v) + if type(v)=="function" then + local ok,str=xpcall(dump,function() end,v) + if ok then + v=str + end + end + if type(v)=="string" then + show(v,true) + else + print(v) + end + end +end end -- closure @@ -4379,3 +4957,560 @@ function stacker.new(name) end end -- closure + +do -- begin closure to overcome local limits and interference + +if not modules then modules={} end modules ['util-zip']={ + version=1.001, + author="Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright="PRAGMA ADE / ConTeXt Development Team", + license="see context related readme files" +} +local type,tostring,tonumber=type,tostring,tonumber +local sort,concat=table.sort,table.concat +local find,format,sub,gsub=string.find,string.format,string.sub,string.gsub +local osdate,ostime,osclock=os.date,os.time,os.clock +local ioopen=io.open +local loaddata,savedata=io.loaddata,io.savedata +local filejoin,isdir,dirname,mkdirs=file.join,lfs.isdir,file.dirname,dir.mkdirs +local suffix,suffixes=file.suffix,file.suffixes +local openfile=io.open +gzip=gzip or {} +if not zlib then + zlib=xzip +elseif not xzip then + xzip=zlib +end +local files=utilities.files +local openfile=files.open +local closefile=files.close +local readstring=files.readstring +local readcardinal2=files.readcardinal2le +local readcardinal4=files.readcardinal4le +local setposition=files.setposition +local getposition=files.getposition +local band=bit32.band +local rshift=bit32.rshift +local lshift=bit32.lshift +local zlibdecompress=zlib.decompress +local zlibdecompresssize=zlib.decompresssize +local zlibchecksum=zlib.crc32 +if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then + local cs=zlibchecksum + zlibchecksum=function(str,n) return cs(n or 0,str) end +end +local decompress=function(source) return zlibdecompress (source,-15) end +local decompresssize=function(source,targetsize) return zlibdecompresssize(source,targetsize,-15) end +local calculatecrc=function(buffer,initial) return zlibchecksum (initial or 0,buffer) end +local zipfiles={} +utilities.zipfiles=zipfiles +local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do + function openzipfile(name) + return { + name=name, + handle=openfile(name,0), + } + end + local function collect(z) + if not z.list then + local list={} + local hash={} + local position=0 + local index=0 + local handle=z.handle + while true do + setposition(handle,position) + local signature=readstring(handle,4) + if signature=="PK\3\4" then + local version=readcardinal2(handle) + local flag=readcardinal2(handle) + local method=readcardinal2(handle) + local filetime=readcardinal2(handle) + local filedate=readcardinal2(handle) + local crc32=readcardinal4(handle) + local compressed=readcardinal4(handle) + local uncompressed=readcardinal4(handle) + local namelength=readcardinal2(handle) + local extralength=readcardinal2(handle) + local filename=readstring(handle,namelength) + local descriptor=band(flag,8)~=0 + local encrypted=band(flag,1)~=0 + local acceptable=method==0 or method==8 + local skipped=0 + local size=0 + if encrypted then + size=readcardinal2(handle) + skipbytes(size) + skipped=skipped+size+2 + skipbytes(8) + skipped=skipped+8 + size=readcardinal2(handle) + skipbytes(size) + skipped=skipped+size+2 + size=readcardinal4(handle) + skipbytes(size) + skipped=skipped+size+4 + size=readcardinal2(handle) + skipbytes(size) + skipped=skipped+size+2 + end + position=position+30+namelength+extralength+skipped + if descriptor then + setposition(handle,position+compressed) + crc32=readcardinal4(handle) + compressed=readcardinal4(handle) + uncompressed=readcardinal4(handle) + end + if acceptable then + index=index+1 + local data={ + filename=filename, + index=index, + position=position, + method=method, + compressed=compressed, + uncompressed=uncompressed, + crc32=crc32, + encrypted=encrypted, + } + hash[filename]=data + list[index]=data + else + end + position=position+compressed + else + break + end + z.list=list + z.hash=hash + end + end + end + function getziplist(z) + local list=z.list + if not list then + collect(z) + end + return z.list + end + function getziphash(z) + local hash=z.hash + if not hash then + collect(z) + end + return z.hash + end + function foundzipfile(z,name) + return getziphash(z)[name] + end + function closezipfile(z) + local f=z.handle + if f then + closefile(f) + z.handle=nil + end + end + function unzipfile(z,filename,check) + local hash=z.hash + if not hash then + hash=zipfiles.hash(z) + end + local data=hash[filename] + if not data then + end + if data then + local handle=z.handle + local position=data.position + local compressed=data.compressed + if compressed>0 then + setposition(handle,position) + local result=readstring(handle,compressed) + if data.method==8 then + if decompresssize then + result=decompresssize(result,data.uncompressed) + else + result=decompress(result) + end + end + if check and data.crc32~=calculatecrc(result) then + print("checksum mismatch") + return "" + end + return result + else + return "" + end + end + end + zipfiles.open=openzipfile + zipfiles.close=closezipfile + zipfiles.unzip=unzipfile + zipfiles.hash=getziphash + zipfiles.list=getziplist + zipfiles.found=foundzipfile +end +if xzip then + local writecardinal1=files.writebyte + local writecardinal2=files.writecardinal2le + local writecardinal4=files.writecardinal4le + local logwriter=logs.writer + local globpattern=dir.globpattern + local compress=xzip.compress + local checksum=xzip.crc32 + local function fromdostime(dostime,dosdate) + return ostime { + year=rshift(dosdate,9)+1980, + month=band(rshift(dosdate,5),0x0F), + day=band((dosdate ),0x1F), + hour=band(rshift(dostime,11) ), + min=band(rshift(dostime,5),0x3F), + sec=band((dostime ),0x1F), + } + end + local function todostime(time) + local t=osdate("*t",time) + return + lshift(t.year-1980,9)+lshift(t.month,5)+t.day, + lshift(t.hour,11)+lshift(t.min,5)+rshift(t.sec,1) + end + local function openzip(filename,level,comment,verbose) + local f=ioopen(filename,"wb") + if f then + return { + filename=filename, + handle=f, + list={}, + level=tonumber(level) or 3, + comment=tostring(comment), + verbose=verbose, + uncompressed=0, + compressed=0, + } + end + end + local function writezip(z,name,data,level,time) + local f=z.handle + local list=z.list + local level=tonumber(level) or z.level or 3 + local method=8 + local zipped=compress(data,level) + local checksum=checksum(data) + local verbose=z.verbose + if not zipped then + method=0 + zipped=data + end + local start=f:seek() + local compressed=#zipped + local uncompressed=#data + z.compressed=z.compressed+compressed + z.uncompressed=z.uncompressed+uncompressed + if verbose then + local pct=100*compressed/uncompressed + if pct>=100 then + logwriter(format("%10i %s",uncompressed,name)) + else + logwriter(format("%10i %02.1f %s",uncompressed,pct,name)) + end + end + f:write("\x50\x4b\x03\x04") + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal2(f,method) + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal4(f,checksum) + writecardinal4(f,compressed) + writecardinal4(f,uncompressed) + writecardinal2(f,#name) + writecardinal2(f,0) + f:write(name) + f:write(zipped) + list[#list+1]={ #zipped,#data,name,checksum,start,time or 0 } + end + local function closezip(z) + local f=z.handle + local list=z.list + local comment=z.comment + local verbose=z.verbose + local count=#list + local start=f:seek() + for i=1,count do + local l=list[i] + local compressed=l[1] + local uncompressed=l[2] + local name=l[3] + local checksum=l[4] + local start=l[5] + local time=l[6] + local date,time=todostime(time) + f:write('\x50\x4b\x01\x02') + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal2(f,8) + writecardinal2(f,time) + writecardinal2(f,date) + writecardinal4(f,checksum) + writecardinal4(f,compressed) + writecardinal4(f,uncompressed) + writecardinal2(f,#name) + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal4(f,0) + writecardinal4(f,start) + f:write(name) + end + local stop=f:seek() + local size=stop-start + f:write('\x50\x4b\x05\x06') + writecardinal2(f,0) + writecardinal2(f,0) + writecardinal2(f,count) + writecardinal2(f,count) + writecardinal4(f,size) + writecardinal4(f,start) + if type(comment)=="string" and comment~="" then + writecardinal2(f,#comment) + f:write(comment) + else + writecardinal2(f,0) + end + if verbose then + local compressed=z.compressed + local uncompressed=z.uncompressed + local filename=z.filename + local pct=100*compressed/uncompressed + logwriter("") + if pct>=100 then + logwriter(format("%10i %s",uncompressed,filename)) + else + logwriter(format("%10i %02.1f %s",uncompressed,pct,filename)) + end + end + f:close() + end + local function zipdir(zipname,path,level,verbose) + if type(zipname)=="table" then + verbose=zipname.verbose + level=zipname.level + path=zipname.path + zipname=zipname.zipname + end + if not zipname or zipname=="" then + return + end + if not path or path=="" then + path="." + end + if not isdir(path) then + return + end + path=gsub(path,"\\+","/") + path=gsub(path,"/+","/") + local list={} + local count=0 + globpattern(path,"",true,function(name,size,time) + count=count+1 + list[count]={ name,time } + end) + sort(list,function(a,b) + return a[1]<b[1] + end) + local zipf=openzip(zipname,level,comment,verbose) + if zipf then + local p=#path+2 + for i=1,count do + local li=list[i] + local name=li[1] + local time=li[2] + local data=loaddata(name) + local name=sub(name,p,#name) + writezip(zipf,name,data,level,time,verbose) + end + closezip(zipf) + end + end + local function unzipdir(zipname,path,verbose) + if type(zipname)=="table" then + verbose=zipname.verbose + path=zipname.path + zipname=zipname.zipname + end + if not zipname or zipname=="" then + return + end + if not path or path=="" then + path="." + end + local z=openzipfile(zipname) + if z then + local list=getziplist(z) + if list then + local total=0 + local count=#list + local step=number.idiv(count,10) + local done=0 + local steps=verbose=="steps" + local time=steps and osclock() + for i=1,count do + local l=list[i] + local n=l.filename + local d=unzipfile(z,n) + if d then + local p=filejoin(path,n) + if mkdirs(dirname(p)) then + if steps then + total=total+#d + done=done+1 + if done>=step then + done=0 + logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",i,count,total,osclock()-time)) + end + elseif verbose then + logwriter(n) + end + savedata(p,d) + end + else + logwriter(format("problem with file %s",n)) + end + end + if steps then + logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",count,count,total,osclock()-time)) + end + closezipfile(z) + return true + else + closezipfile(z) + end + end + end + zipfiles.zipdir=zipdir + zipfiles.unzipdir=unzipdir +end +local pattern="^\x1F\x8B\x08" +local gziplevel=3 +function gzip.suffix(filename) + local suffix,extra=suffixes(filename) + local gzipped=extra=="gz" + return suffix,gzipped +end +function gzip.compressed(s) + return s and find(s,pattern) +end +local getdecompressed +local putcompressed +if gzip.compress then + local gzipwindow=15+16 + local compress=zlib.compress + local decompress=zlib.decompress + getdecompressed=function(str) + return decompress(str,gzipwindow) + end + putcompressed=function(str,level) + return compress(str,level or gziplevel,nil,gzipwindow) + end +else + local gzipwindow=-15 + local identifier="\x1F\x8B" + local compress=zlib.compress + local decompress=zlib.decompress + local zlibchecksum=zlib.crc32 + if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then + local cs=zlibchecksum + zlibchecksum=function(str,n) return cs(n or 0,str) end + end + local streams=utilities.streams + local openstream=streams.openstring + local closestream=streams.close + local getposition=streams.getposition + local readbyte=streams.readbyte + local readcardinal4=streams.readcardinal4le + local readcardinal2=streams.readcardinal2le + local readstring=streams.readstring + local readcstring=streams.readcstring + local skipbytes=streams.skip + local tocardinal1=streams.tocardinal1 + local tocardinal4=streams.tocardinal4le + getdecompressed=function(str) + local s=openstream(str) + local identifier=readstring(s,2) + local method=readbyte(s,1) + local flags=readbyte(s,1) + local timestamp=readcardinal4(s) + local compression=readbyte(s,1) + local operating=readbyte(s,1) + local isjusttext=band(flags,0x01)~=0 and true or false + local extrasize=band(flags,0x04)~=0 and readcardinal2(s) or 0 + local filename=band(flags,0x08)~=0 and readcstring(s) or "" + local comment=band(flags,0x10)~=0 and readcstring(s) or "" + local checksum=band(flags,0x02)~=0 and readcardinal2(s) or 0 + local compressed=readstring(s,#str) + local data=decompress(compressed,gzipwindow) + return data + end + putcompressed=function(str,level,originalname) + return concat { + identifier, + tocardinal1(0x08), + tocardinal1(0x08), + tocardinal4(os.time()), + tocardinal1(0x02), + tocardinal1(0xFF), + (originalname or "unknownname").."\0", + compress(str,level,nil,gzipwindow), + tocardinal4(zlibchecksum(str)), + tocardinal4(#str), + } + end +end +function gzip.load(filename) + local f=openfile(filename,"rb") + if not f then + else + local data=f:read("*all") + f:close() + if data and data~="" then + if suffix(filename)=="gz" then + data=getdecompressed(data) + end + return data + end + end +end +function gzip.save(filename,data,level,originalname) + if suffix(filename)~="gz" then + filename=filename..".gz" + end + local f=openfile(filename,"wb") + if f then + data=putcompressed(data or "",level or gziplevel,originalname) + f:write(data) + f:close() + return #data + end +end +function gzip.compress(s,level) + if s and not find(s,pattern) then + if not level then + level=gziplevel + elseif level<=0 then + return s + elseif level>9 then + level=9 + end + return putcompressed(s,level or gziplevel) or s + end +end +function gzip.decompress(s) + if s and find(s,pattern) then + return getdecompressed(s) + else + return s + end +end + +end -- closure |