diff options
author | Karl Berry <karl@freefriends.org> | 2019-07-14 20:48:50 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-07-14 20:48:50 +0000 |
commit | 03b40659365a55ac7b166e6d8afe7dcf94047115 (patch) | |
tree | 41fc3ac8a6e0023ec7bb02ade93b05c594a33701 /Master/texmf-dist/tex | |
parent | 43f963c6e7c57e4278ebb7644cef82b408d66f95 (diff) |
lualibs (14jul19)
git-svn-id: svn://tug.org/texlive/trunk@51642 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
7 files changed, 678 insertions, 237 deletions
diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua index bc4e3290873..7d5e0d07b1a 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua @@ -1,6 +1,6 @@ -- merged file : lualibs-basic-merged.lua -- parent file : lualibs-basic.lua --- merge date : Sat May 18 17:39:21 2019 +-- merge date : Sun Jul 14 15:31:33 2019 do -- begin closure to overcome local limits and interference @@ -1294,9 +1294,11 @@ function string.is_empty(str) end end local anything=patterns.anything -local allescapes=Cc("%")*S(".-+%?()[]*") -local someescapes=Cc("%")*S(".-+%()[]") -local matchescapes=Cc(".")*S("*?") +local moreescapes=Cc("%")*S(".-+%?()[]*$^{}") +local allescapes=Cc("%")*S(".-+%?()[]*") +local someescapes=Cc("%")*S(".-+%()[]") +local matchescapes=Cc(".")*S("*?") +local pattern_m=Cs ((moreescapes+anything )^0 ) local pattern_a=Cs ((allescapes+anything )^0 ) local pattern_b=Cs ((someescapes+matchescapes+anything )^0 ) local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") ) @@ -1306,6 +1308,8 @@ end function string.topattern(str,lowercase,strict) if str=="" or type(str)~="string" then return ".*" + elseif strict=="all" then + str=lpegmatch(pattern_m,str) elseif strict then str=lpegmatch(pattern_c,str) else diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua index 40431c79e84..d04c8eebe49 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua @@ -29,8 +29,8 @@ local loadmodule = lualibs.loadmodule local lualibs_basic_module = { name = "lualibs-basic", - version = 2.65, - date = "2019-05-18", + version = 2.66, + date = "2019-07-04", description = "ConTeXt Lua libraries -- basic collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua index afd99067725..672787f9e50 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua @@ -1,6 +1,6 @@ -- merged file : lualibs-extended-merged.lua -- parent file : lualibs-extended.lua --- merge date : Sat May 18 17:39:12 2019 +-- merge date : Sun Jul 14 15:31:26 2019 do -- begin closure to overcome local limits and interference @@ -2762,121 +2762,325 @@ if not modules then modules={} end modules ['util-jsn']={ 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 +local formatters=string.formatters local utfchar=utf.char -local concat=table.concat +local concat,sortedkeys=table.concat,table.sortedkeys local tonumber,tostring,rawset,type,next=tonumber,tostring,rawset,type,next local json=utilities.json or {} utilities.json=json -local lbrace=P("{") -local rbrace=P("}") -local lparent=P("[") -local rparent=P("]") -local comma=P(",") -local colon=P(":") -local dquote=P('"') -local whitespace=lpeg.patterns.whitespace -local optionalws=whitespace^0 -local escapes={ - ["b"]="\010", - ["f"]="\014", - ["n"]="\n", - ["r"]="\r", - ["t"]="\t", -} -local escape_un=P("\\u")/""*(C(R("09","AF","af")^-4)/function(s) - return utfchar(tonumber(s,16)) -end) -local escape_bs=P([[\]])/""*(P(1)/escapes) -local jstring=dquote*Cs((escape_un+escape_bs+(1-dquote))^0)*dquote -local jtrue=P("true")*Cc(true) -local jfalse=P("false")*Cc(false) -local jnull=P("null")*Cc(nil) -local jnumber=(1-whitespace-rparent-rbrace-comma)^1/tonumber -local key=jstring -local jsonconverter={ "value", - hash=lbrace*Cf(Ct("")*(V("pair")*(comma*V("pair"))^0+optionalws),rawset)*rbrace, - pair=Cg(optionalws*key*optionalws*colon*V("value")), - array=Ct(lparent*(V("value")*(comma*V("value"))^0+optionalws)*rparent), - value=optionalws*(jstring+V("hash")+V("array")+jtrue+jfalse+jnull+jnumber)*optionalws, -} -function json.tolua(str) - return lpegmatch(jsonconverter,str) -end -local escaper -local function tojson(value,t,n) - local kind=type(value) - if kind=="table" then - local done=false - local size=#value - if size==0 then - for k,v in next,value do - if done then - n=n+1;t[n]="," +do + local lbrace=P("{") + local rbrace=P("}") + local lparent=P("[") + local rparent=P("]") + local comma=P(",") + local colon=P(":") + local dquote=P('"') + local whitespace=lpeg.patterns.whitespace + local optionalws=whitespace^0 + local escapes={ + ["b"]="\010", + ["f"]="\014", + ["n"]="\n", + ["r"]="\r", + ["t"]="\t", + } + local escape_un=P("\\u")/""*(C(R("09","AF","af")^-4)/function(s) + return utfchar(tonumber(s,16)) + end) + local escape_bs=P([[\]])/""*(P(1)/escapes) + local jstring=dquote*Cs((escape_un+escape_bs+(1-dquote))^0)*dquote + local jtrue=P("true")*Cc(true) + local jfalse=P("false")*Cc(false) + local jnull=P("null")*Cc(nil) + local jnumber=(1-whitespace-rparent-rbrace-comma)^1/tonumber + local key=jstring + local jsonconverter={ "value", + hash=lbrace*Cf(Ct("")*(V("pair")*(comma*V("pair"))^0+optionalws),rawset)*rbrace, + pair=Cg(optionalws*key*optionalws*colon*V("value")), + array=Ct(lparent*(V("value")*(comma*V("value"))^0+optionalws)*rparent), + value=optionalws*(jstring+V("hash")+V("array")+jtrue+jfalse+jnull+jnumber)*optionalws, + } + function json.tolua(str) + return lpegmatch(jsonconverter,str) + end + function json.load(filename) + local data=io.loaddata(filename) + if data then + return lpegmatch(jsonconverter,data) + end + end +end +do + local escaper + local f_start_hash=formatters[ '%w{' ] + local f_start_array=formatters[ '%w[' ] + local f_start_hash_new=formatters[ "\n"..'%w{' ] + local f_start_array_new=formatters[ "\n"..'%w[' ] + local f_start_hash_key=formatters[ "\n"..'%w"%s" : {' ] + local f_start_array_key=formatters[ "\n"..'%w"%s" : [' ] + local f_stop_hash=formatters[ "\n"..'%w}' ] + local f_stop_array=formatters[ "\n"..'%w]' ] + local f_key_val_seq=formatters[ "\n"..'%w"%s" : %s' ] + local f_key_val_str=formatters[ "\n"..'%w"%s" : "%s"' ] + local f_key_val_num=f_key_val_seq + local f_key_val_yes=formatters[ "\n"..'%w"%s" : true' ] + local f_key_val_nop=formatters[ "\n"..'%w"%s" : false' ] + local f_val_num=formatters[ "\n"..'%w%s' ] + local f_val_str=formatters[ "\n"..'%w"%s"' ] + local f_val_yes=formatters[ "\n"..'%wtrue' ] + local f_val_nop=formatters[ "\n"..'%wfalse' ] + local f_val_seq=f_val_num + local t={} + local n=0 + local function is_simple_table(tt) + local l=#tt + if l>0 then + for i=1,l do + if type(tt[i])=="table" then + return false + end + end + local nn=n + n=n+1 t[n]="[ " + for i=1,l do + if i>1 then + n=n+1 t[n]=", " + end + local v=tt[i] + local tv=type(v) + if tv=="number" then + n=n+1 t[n]=v + elseif tv=="string" then + n=n+1 t[n]='"' + n=n+1 t[n]=lpegmatch(escaper,v) or v + n=n+1 t[n]='"' + elseif tv=="boolean" then + n=n+1 t[n]=v and "true" or "false" else - n=n+1;t[n]="{" - done=true + n=n+1 t[n]=tostring(v) end - n=n+1;t[n]=format("%q:",k) - t,n=tojson(v,t,n) end - if done then - n=n+1;t[n]="}" + n=n+1 t[n]=" ]" + local s=concat(t,"",nn+1,n) + n=nn + return s + end + return false + end + local function tojsonpp(root,name,depth,level,size) + if root then + local indexed=size>0 + n=n+1 + if level==0 then + if indexed then + t[n]=f_start_array(depth) + else + t[n]=f_start_hash(depth) + end + elseif name then + if tn=="string" then + name=lpegmatch(escaper,name) or name + elseif tn~="number" then + name=tostring(name) + end + if indexed then + t[n]=f_start_array_key(depth,name) + else + t[n]=f_start_hash_key(depth,name) + end else - n=n+1;t[n]="{}" + if indexed then + t[n]=f_start_array_new(depth) + else + t[n]=f_start_hash_new(depth) + end end - elseif size==1 then - n=n+1;t[n]="[" - t,n=tojson(value[1],t,n) - n=n+1;t[n]="]" - else - for i=1,size do + depth=depth+1 + if indexed then + for i=1,size do + if i>1 then + n=n+1 t[n]="," + end + local v=root[i] + local tv=type(v) + if tv=="number" then + n=n+1 t[n]=f_val_num(depth,v) + elseif tv=="string" then + v=lpegmatch(escaper,v) or v + n=n+1 t[n]=f_val_str(depth,v) + elseif tv=="table" then + if next(v) then + local st=is_simple_table(v) + if st then + n=n+1 t[n]=f_val_seq(depth,st) + else + tojsonpp(v,k,depth,level+1,0) + end + end + elseif tv=="boolean" then + n=n+1 + if v then + t[n]=f_val_yes(depth,v) + else + t[n]=f_val_nop(depth,v) + end + end + end + elseif next(root) then + local sk=sortedkeys(root) + for i=1,#sk do + if i>1 then + n=n+1 t[n]="," + end + local k=sk[i] + local v=root[k] + local tv=type(v) + local tk=type(k) + if tv=="number" then + if tk=="number" then + n=n+1 t[n]=f_key_val_num(depth,k,v) + elseif tk=="string" then + k=lpegmatch(escaper,k) or k + n=n+1 t[n]=f_key_val_str(depth,k,v) + end + elseif tv=="string" then + if tk=="number" then + v=lpegmatch(escaper,v) or v + n=n+1 t[n]=f_key_val_num(depth,k,v) + elseif tk=="string" then + k=lpegmatch(escaper,k) or k + v=lpegmatch(escaper,v) or v + n=n+1 t[n]=f_key_val_str(depth,k,v) + end + elseif tv=="table" then + local l=#v + if l>0 then + local st=is_simple_table(v) + if not st then + tojsonpp(v,k,depth,level+1,l) + elseif tk=="number" then + n=n+1 t[n]=f_key_val_seq(depth,k,st) + elseif tk=="string" then + k=lpegmatch(escaper,k) or k + n=n+1 t[n]=f_key_val_seq(depth,k,st) + end + elseif next(v) then + tojsonpp(v,k,depth,level+1,0) + end + elseif tv=="boolean" then + if tk=="number" then + n=n+1 + if v then + t[n]=f_key_val_yes(depth,k) + else + t[n]=f_key_val_nop(depth,k) + end + elseif tk=="string" then + k=lpegmatch(escaper,k) or k + n=n+1 + if v then + t[n]=f_key_val_yes(depth,k) + else + t[n]=f_key_val_nop(depth,k) + end + end + end + end + end + n=n+1 + if indexed then + t[n]=f_stop_array(depth-1) + else + t[n]=f_stop_hash(depth-1) + end + end + end + local function tojson(value,n) + local kind=type(value) + if kind=="table" then + local done=false + local size=#value + if size==0 then + for k,v in next,value do + if done then + n=n+1;t[n]=',"' + else + n=n+1;t[n]='{"' + done=true + end + n=n+1;t[n]=lpegmatch(escaper,k) or k + n=n+1;t[n]='":' + t,n=tojson(v,n) + end if done then - n=n+1;t[n]="," + n=n+1;t[n]="}" else - n=n+1;t[n]="[" - done=true + n=n+1;t[n]="{}" + end + elseif size==1 then + n=n+1;t[n]="[" + t,n=tojson(value[1],n) + n=n+1;t[n]="]" + else + for i=1,size do + if done then + n=n+1;t[n]="," + else + n=n+1;t[n]="[" + done=true + end + t,n=tojson(value[i],n) + end + n=n+1;t[n]="]" + end + elseif kind=="string" then + n=n+1;t[n]='"' + n=n+1;t[n]=lpegmatch(escaper,value) or value + n=n+1;t[n]='"' + elseif kind=="number" then + n=n+1;t[n]=value + elseif kind=="boolean" then + n=n+1;t[n]=tostring(value) + end + return t,n + end + local function jsontostring(value,pretty) + local kind=type(value) + if kind=="table" then + if not escaper then + local escapes={ + ["\\"]="\\u005C", + ["\""]="\\u0022", + } + for i=0,0x1F do + escapes[utfchar(i)]=format("\\u%04X",i) end - t,n=tojson(value[i],t,n) + escaper=Cs(( + (R('\0\x20')+S('\"\\'))/escapes+P(1) + )^1 ) end - n=n+1;t[n]="]" - end - elseif kind=="string" then - n=n+1;t[n]='"' - n=n+1;t[n]=lpegmatch(escaper,value) or value - n=n+1;t[n]='"' - elseif kind=="number" then - n=n+1;t[n]=value - elseif kind=="boolean" then - n=n+1;t[n]=tostring(value) - end - return t,n -end -function json.tostring(value) - local kind=type(value) - if kind=="table" then - if not escaper then - local escapes={ - ["\\"]="\\u005C", - ["\""]="\\u0022", - } - for i=0,0x20 do - escapes[utfchar(i)]=format("\\u%04X",i) + t={} + n=0 + if pretty then + tojsonpp(value,name,0,0,#value) + value=concat(t,"",1,n) + else + tojson(value,0) + value=concat(t,"",1,n) end - escaper=Cs(( - (R('\0\x20')+S('\"\\'))/escapes+P(1) - )^1 ) + t=nil + n=0 + return value + elseif kind=="string" or kind=="number" then + return lpegmatch(escaper,value) or value + else + return tostring(value) end - return concat((tojson(value,{},0))) - elseif kind=="string" or kind=="number" then - return lpegmatch(escaper,value) or value - else - return tostring(value) end -end -function json.load(filename) - local data=io.loaddata(filename) - if data then - return lpegmatch(jsonconverter,data) + json.tostring=jsontostring + function json.tojson(value) + return jsontostring(value,true) end end return json diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua index 1f5fcc5a9d7..1013fe54580 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua @@ -30,8 +30,8 @@ lualibs = lualibs or { } local lualibs_extended_module = { name = "lualibs-extended", - version = 2.65, - date = "2019-05-18", + version = 2.66, + date = "2019-07-04", description = "ConTeXt Lua libraries -- extended collection.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua index 8ae8d8d1d76..1dee85e2894 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-string.lua @@ -155,11 +155,13 @@ end --- needs checking local anything = patterns.anything -local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ? -local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ? -local matchescapes = Cc(".") * S("*?") -- wildcard and single match +local moreescapes = Cc("%") * S(".-+%?()[]*$^{}") +local allescapes = Cc("%") * S(".-+%?()[]*") -- also {} and ^$ ? +local someescapes = Cc("%") * S(".-+%()[]") -- also {} and ^$ ? +local matchescapes = Cc(".") * S("*?") -- wildcard and single match -local pattern_a = Cs ( ( allescapes + anything )^0 ) +local pattern_m = Cs ( ( moreescapes + anything )^0 ) +local pattern_a = Cs ( ( allescapes + anything )^0 ) local pattern_b = Cs ( ( someescapes + matchescapes + anything )^0 ) local pattern_c = Cs ( Cc("^") * ( someescapes + matchescapes + anything )^0 * Cc("$") ) @@ -170,6 +172,8 @@ end function string.topattern(str,lowercase,strict) if str == "" or type(str) ~= "string" then return ".*" + elseif strict == "all" then + str = lpegmatch(pattern_m,str) elseif strict then str = lpegmatch(pattern_c,str) else diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua index acbf160904d..68c6a712edd 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua @@ -20,155 +20,391 @@ if not modules then modules = { } end modules ['util-jsn'] = { 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 +local formatters = string.formatters local utfchar = utf.char -local concat = table.concat +local concat, sortedkeys = table.concat, table.sortedkeys local tonumber, tostring, rawset, type, next = tonumber, tostring, rawset, type, next local json = utilities.json or { } utilities.json = json --- \\ \/ \b \f \n \r \t \uHHHH - -local lbrace = P("{") -local rbrace = P("}") -local lparent = P("[") -local rparent = P("]") -local comma = P(",") -local colon = P(":") -local dquote = P('"') - -local whitespace = lpeg.patterns.whitespace -local optionalws = whitespace^0 - -local escapes = { - ["b"] = "\010", - ["f"] = "\014", - ["n"] = "\n", - ["r"] = "\r", - ["t"] = "\t", -} +do --- todo: also handle larger utf16 + -- \\ \/ \b \f \n \r \t \uHHHH -local escape_un = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s) - return utfchar(tonumber(s,16)) -end) + local lbrace = P("{") + local rbrace = P("}") + local lparent = P("[") + local rparent = P("]") + local comma = P(",") + local colon = P(":") + local dquote = P('"') -local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char + local whitespace = lpeg.patterns.whitespace + local optionalws = whitespace^0 -local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote -local jtrue = P("true") * Cc(true) -local jfalse = P("false") * Cc(false) -local jnull = P("null") * Cc(nil) -local jnumber = (1-whitespace-rparent-rbrace-comma)^1 / tonumber + local escapes = { + ["b"] = "\010", + ["f"] = "\014", + ["n"] = "\n", + ["r"] = "\r", + ["t"] = "\t", + } -local key = jstring + -- todo: also handle larger utf16 -local jsonconverter = { "value", - hash = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace, - pair = Cg(optionalws * key * optionalws * colon * V("value")), - array = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent), --- value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws, - value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws, -} + local escape_un = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s) + return utfchar(tonumber(s,16)) + end) + + local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char + + local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote + local jtrue = P("true") * Cc(true) + local jfalse = P("false") * Cc(false) + local jnull = P("null") * Cc(nil) + local jnumber = (1-whitespace-rparent-rbrace-comma)^1 / tonumber + + local key = jstring + + local jsonconverter = { "value", + hash = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace, + pair = Cg(optionalws * key * optionalws * colon * V("value")), + array = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent), + -- value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws, + value = optionalws * (jstring + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws, + } + + -- local jsonconverter = { "value", + -- hash = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace, + -- pair = Cg(optionalws * V("string") * optionalws * colon * V("value")), + -- array = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent), + -- string = jstring, + -- value = optionalws * (V("string") + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws, + -- } + + -- lpeg.print(jsonconverter) -- size 181 --- local jsonconverter = { "value", --- hash = lbrace * Cf(Ct("") * (V("pair") * (comma * V("pair"))^0 + optionalws),rawset) * rbrace, --- pair = Cg(optionalws * V("string") * optionalws * colon * V("value")), --- array = Ct(lparent * (V("value") * (comma * V("value"))^0 + optionalws) * rparent), --- string = jstring, --- value = optionalws * (V("string") + V("hash") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws, --- } + function json.tolua(str) + return lpegmatch(jsonconverter,str) + end --- lpeg.print(jsonconverter) -- size 181 + function json.load(filename) + local data = io.loaddata(filename) + if data then + return lpegmatch(jsonconverter,data) + end + end -function json.tolua(str) - return lpegmatch(jsonconverter,str) end -local escaper +do -local function tojson(value,t,n) -- we could optimize #t - local kind = type(value) - if kind == "table" then - local done = false - local size = #value - if size == 0 then - for k, v in next, value do - if done then - n = n + 1 ; t[n] = "," + -- It's pretty bad that JSON doesn't allow the trailing comma ... it's a + -- typical example of a spec that then forces all generators to check for + -- this. It's a way to make sure programmers keep jobs. + + local escaper + + local f_start_hash = formatters[ '%w{' ] + local f_start_array = formatters[ '%w[' ] + local f_start_hash_new = formatters[ "\n" .. '%w{' ] + local f_start_array_new = formatters[ "\n" .. '%w[' ] + local f_start_hash_key = formatters[ "\n" .. '%w"%s" : {' ] + local f_start_array_key = formatters[ "\n" .. '%w"%s" : [' ] + + local f_stop_hash = formatters[ "\n" .. '%w}' ] + local f_stop_array = formatters[ "\n" .. '%w]' ] + + local f_key_val_seq = formatters[ "\n" .. '%w"%s" : %s' ] + local f_key_val_str = formatters[ "\n" .. '%w"%s" : "%s"' ] + local f_key_val_num = f_key_val_seq + local f_key_val_yes = formatters[ "\n" .. '%w"%s" : true' ] + local f_key_val_nop = formatters[ "\n" .. '%w"%s" : false' ] + + local f_val_num = formatters[ "\n" .. '%w%s' ] + local f_val_str = formatters[ "\n" .. '%w"%s"' ] + local f_val_yes = formatters[ "\n" .. '%wtrue' ] + local f_val_nop = formatters[ "\n" .. '%wfalse' ] + local f_val_seq = f_val_num + + -- no empty tables because unknown if table or hash + + local t = { } + local n = 0 + + local function is_simple_table(tt) -- also used in util-tab so maybe public + local l = #tt + if l > 0 then + for i=1,l do + if type(tt[i]) == "table" then + return false + end + end + local nn = n + n = n + 1 t[n] = "[ " + for i=1,l do + if i > 1 then + n = n + 1 t[n] = ", " + end + local v = tt[i] + local tv = type(v) + if tv == "number" then + n = n + 1 t[n] = v + elseif tv == "string" then + n = n + 1 t[n] = '"' + n = n + 1 t[n] = lpegmatch(escaper,v) or v + n = n + 1 t[n] = '"' + elseif tv == "boolean" then + n = n + 1 t[n] = v and "true" or "false" else - n = n + 1 ; t[n] = "{" - done = true + n = n + 1 t[n] = tostring(v) end - n = n + 1 ; t[n] = format("%q:",k) - t, n = tojson(v,t,n) end - if done then - n = n + 1 ; t[n] = "}" + n = n + 1 t[n] = " ]" + local s = concat(t,"",nn+1,n) + n = nn + return s + end + return false + end + + local function tojsonpp(root,name,depth,level,size) + if root then + local indexed = size > 0 + n = n + 1 + if level == 0 then + if indexed then + t[n] = f_start_array(depth) + else + t[n] = f_start_hash(depth) + end + elseif name then + if tn == "string" then + name = lpegmatch(escaper,name) or name + elseif tn ~= "number" then + name = tostring(name) + end + if indexed then + t[n] = f_start_array_key(depth,name) + else + t[n] = f_start_hash_key(depth,name) + end else - n = n + 1 ; t[n] = "{}" + if indexed then + t[n] = f_start_array_new(depth) + else + t[n] = f_start_hash_new(depth) + end end - elseif size == 1 then - -- we can optimize for non tables - n = n + 1 ; t[n] = "[" - t, n = tojson(value[1],t,n) - n = n + 1 ; t[n] = "]" - else - for i=1,size do + depth = depth + 1 + if indexed then -- indexed + for i=1,size do + if i > 1 then + n = n + 1 t[n] = "," + end + local v = root[i] + local tv = type(v) + if tv == "number" then + n = n + 1 t[n] = f_val_num(depth,v) + elseif tv == "string" then + v = lpegmatch(escaper,v) or v + n = n + 1 t[n] = f_val_str(depth,v) + elseif tv == "table" then + if next(v) then + local st = is_simple_table(v) + if st then + n = n + 1 t[n] = f_val_seq(depth,st) + else + tojsonpp(v,k,depth,level+1,0) + end + end + elseif tv == "boolean" then + n = n + 1 + if v then + t[n] = f_val_yes(depth,v) + else + t[n] = f_val_nop(depth,v) + end + end + end + elseif next(root) then + local sk = sortedkeys(root) + for i=1,#sk do + if i > 1 then + n = n + 1 t[n] = "," + end + local k = sk[i] + local v = root[k] + local tv = type(v) + local tk = type(k) + if tv == "number" then + if tk == "number" then + n = n + 1 t[n] = f_key_val_num(depth,k,v) + elseif tk == "string" then + k = lpegmatch(escaper,k) or k + n = n + 1 t[n] = f_key_val_str(depth,k,v) + end + elseif tv == "string" then + if tk == "number" then + v = lpegmatch(escaper,v) or v + n = n + 1 t[n] = f_key_val_num(depth,k,v) + elseif tk == "string" then + k = lpegmatch(escaper,k) or k + v = lpegmatch(escaper,v) or v + n = n + 1 t[n] = f_key_val_str(depth,k,v) + end + elseif tv == "table" then + local l = #v + if l > 0 then + local st = is_simple_table(v) + if not st then + tojsonpp(v,k,depth,level+1,l) + elseif tk == "number" then + n = n + 1 t[n] = f_key_val_seq(depth,k,st) + elseif tk == "string" then + k = lpegmatch(escaper,k) or k + n = n + 1 t[n] = f_key_val_seq(depth,k,st) + end + elseif next(v) then + tojsonpp(v,k,depth,level+1,0) + end + elseif tv == "boolean" then + if tk == "number" then + n = n + 1 + if v then + t[n] = f_key_val_yes(depth,k) + else + t[n] = f_key_val_nop(depth,k) + end + elseif tk == "string" then + k = lpegmatch(escaper,k) or k + n = n + 1 + if v then + t[n] = f_key_val_yes(depth,k) + else + t[n] = f_key_val_nop(depth,k) + end + end + end + end + end + n = n + 1 + if indexed then + t[n] = f_stop_array(depth-1) + else + t[n] = f_stop_hash(depth-1) + end + end + end + + local function tojson(value,n) + local kind = type(value) + if kind == "table" then + local done = false + local size = #value + if size == 0 then + for k, v in next, value do + if done then + -- n = n + 1 ; t[n] = "," + n = n + 1 ; t[n] = ',"' + else + -- n = n + 1 ; t[n] = "{" + n = n + 1 ; t[n] = '{"' + done = true + end + n = n + 1 ; t[n] = lpegmatch(escaper,k) or k + n = n + 1 ; t[n] = '":' + t, n = tojson(v,n) + end if done then - n = n + 1 ; t[n] = "," + n = n + 1 ; t[n] = "}" else - n = n + 1 ; t[n] = "[" - done = true + n = n + 1 ; t[n] = "{}" end - t, n = tojson(value[i],t,n) + elseif size == 1 then + -- we can optimize for non tables + n = n + 1 ; t[n] = "[" + t, n = tojson(value[1],n) + n = n + 1 ; t[n] = "]" + else + for i=1,size do + if done then + n = n + 1 ; t[n] = "," + else + n = n + 1 ; t[n] = "[" + done = true + end + t, n = tojson(value[i],n) + end + n = n + 1 ; t[n] = "]" end - n = n + 1 ; t[n] = "]" + elseif kind == "string" then + n = n + 1 ; t[n] = '"' + n = n + 1 ; t[n] = lpegmatch(escaper,value) or value + n = n + 1 ; t[n] = '"' + elseif kind == "number" then + n = n + 1 ; t[n] = value + elseif kind == "boolean" then + n = n + 1 ; t[n] = tostring(value) end - elseif kind == "string" then - n = n + 1 ; t[n] = '"' - n = n + 1 ; t[n] = lpegmatch(escaper,value) or value - n = n + 1 ; t[n] = '"' - elseif kind == "number" then - n = n + 1 ; t[n] = value - elseif kind == "boolean" then - n = n + 1 ; t[n] = tostring(value) + return t, n end - return t, n -end -function json.tostring(value) - -- todo optimize for non table - local kind = type(value) - if kind == "table" then - if not escaper then - local escapes = { - ["\\"] = "\\u005C", - ["\""] = "\\u0022", - } - for i=0,0x20 do - escapes[utfchar(i)] = format("\\u%04X",i) - end - escaper = Cs( ( - (R('\0\x20') + S('\"\\')) / escapes - + P(1) - )^1 ) + -- escaping keys can become an option + + local function jsontostring(value,pretty) + -- todo optimize for non table + local kind = type(value) + if kind == "table" then + if not escaper then + local escapes = { + ["\\"] = "\\u005C", + ["\""] = "\\u0022", + } + for i=0,0x1F do + escapes[utfchar(i)] = format("\\u%04X",i) + end + escaper = Cs( ( + (R('\0\x20') + S('\"\\')) / escapes + + P(1) + )^1 ) + end + -- local to the closure (saves wrapping and local functions) + t = { } + n = 0 + if pretty then + tojsonpp(value,name,0,0,#value) +-- value = concat(t,"\n",1,n) + value = concat(t,"",1,n) + else + tojson(value,0) + value = concat(t,"",1,n) + end + t = nil + n = 0 + return value + elseif kind == "string" or kind == "number" then + return lpegmatch(escaper,value) or value + else + return tostring(value) end - return concat((tojson(value,{},0))) - elseif kind == "string" or kind == "number" then - return lpegmatch(escaper,value) or value - else - return tostring(value) end + + json.tostring = jsontostring + + function json.tojson(value) + return jsontostring(value,true) + end + end --- local tmp = [[ { "t" : "foobar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]] +-- local tmp = [[ { "t\nt t" : "foo bar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]] -- tmp = json.tolua(tmp) -- inspect(tmp) --- tmp = json.tostring(tmp) +-- tmp = json.tostring(tmp,true) -- inspect(tmp) -- tmp = json.tolua(tmp) -- inspect(tmp) @@ -176,13 +412,6 @@ end -- inspect(tmp) -- inspect(json.tostring(true)) -function json.load(filename) - local data = io.loaddata(filename) - if data then - return lpegmatch(jsonconverter,data) - end -end - -- local s = [[\foo"bar"]] -- local j = json.tostring { s = s } -- local l = json.tolua(j) diff --git a/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua b/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua index 089a7441dd2..02243c8df47 100644 --- a/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua +++ b/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua @@ -25,8 +25,8 @@ lualibs = lualibs or { } lualibs.module_info = { name = "lualibs", - version = 2.65, - date = "2019-05-18", + version = 2.66, + date = "2019-07-04", description = "ConTeXt Lua standard libraries.", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang", copyright = "PRAGMA ADE / ConTeXt Development Team", @@ -79,13 +79,13 @@ do lualibs.error, lualibs.warn, lualibs.info = error, warn, info end -if luatexbase and luatexbase.find_file then - find_file = luatexbase.find_file -else - kpse.set_program_name"luatex" - find_file = kpsefind_file +local info = status.list() +if info.kpse_used == 0 then + kpse.set_program_name("luatex") end +find_file = kpsefind_file + local loadmodule = loadmodule or function (name, t) if not t then t = "library" end |