diff options
Diffstat (limited to 'tex/context/base/mkiv/l-io.lua')
-rw-r--r-- | tex/context/base/mkiv/l-io.lua | 281 |
1 files changed, 198 insertions, 83 deletions
diff --git a/tex/context/base/mkiv/l-io.lua b/tex/context/base/mkiv/l-io.lua index a91d44d87..75e704a34 100644 --- a/tex/context/base/mkiv/l-io.lua +++ b/tex/context/base/mkiv/l-io.lua @@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['l-io'] = { } local io = io +local open, flush, write, read = io.open, io.flush, io.write, io.read local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format local concat = table.concat local floor = math.floor @@ -18,59 +19,136 @@ else io.fileseparator, io.pathseparator = "/" , ":" end -local function readall(f) - return f:read("*all") -end +-- local function readall(f) +-- return f:read("*all") +-- end -- The next one is upto 50% faster on large files and less memory consumption due -- to less intermediate large allocations. This phenomena was discussed on the -- luatex dev list. +local large = 2^24 -- 16 MB +local medium = large / 16 -- 1 MB +local small = medium / 8 + +-- local function readall(f) +-- local size = f:seek("end") +-- if size == 0 then +-- return "" +-- end +-- f:seek("set",0) +-- if size < medium then +-- return f:read('*all') +-- else +-- local step = (size > large) and large or (floor(size/(medium)) * small) +-- local data = { } +-- while true do +-- local r = f:read(step) +-- if not r then +-- return concat(data) +-- else +-- data[#data+1] = r +-- end +-- end +-- end +-- end + local function readall(f) +-- return f:read("*all") local size = f:seek("end") - if size == 0 then - return "" - elseif size < 1024*1024 then + if size > 0 then f:seek("set",0) - return f:read('*all') + return f:read(size) else - local done = f:seek("set",0) - local step - if size < 1024*1024 then - step = 1024 * 1024 - elseif size > 16*1024*1024 then - step = 16*1024*1024 - else - step = floor(size/(1024*1024)) * 1024 * 1024 / 8 - end - local data = { } - while true do - local r = f:read(step) - if not r then - return concat(data) - else - data[#data+1] = r - end - end + return "" end end io.readall = readall function io.loaddata(filename,textmode) -- return nil if empty - local f = io.open(filename,(textmode and 'r') or 'rb') + local f = open(filename,(textmode and 'r') or 'rb') if f then - -- local data = f:read('*all') - local data = readall(f) + local size = f:seek("end") + local data = nil + if size > 0 then + -- data = f:read("*all") + f:seek("set",0) + data = f:read(size) + end f:close() - if #data > 0 then - return data + return data + end +end + +-- function io.copydata(source,target,action) +-- local f = open(source,"rb") +-- if f then +-- local g = open(target,"wb") +-- if g then +-- local size = f:seek("end") +-- if size == 0 then +-- -- empty +-- else +-- f:seek("set",0) +-- if size < medium then +-- local data = f:read('*all') +-- if action then +-- data = action(data) +-- end +-- if data then +-- g:write(data) +-- end +-- else +-- local step = (size > large) and large or (floor(size/(medium)) * small) +-- while true do +-- local data = f:read(step) +-- if data then +-- if action then +-- data = action(data) +-- end +-- if data then +-- g:write(data) +-- end +-- else +-- break +-- end +-- end +-- end +-- end +-- g:close() +-- end +-- f:close() +-- flush() +-- end +-- end + +function io.copydata(source,target,action) + local f = open(source,"rb") + if f then + local g = open(target,"wb") + if g then + local size = f:seek("end") + if size > 0 then + -- local data = f:read('*all') + f:seek("set",0) + local data = f:read(size) + if action then + data = action(data) + end + if data then + g:write(data) + end + end + g:close() end + f:close() + flush() end end function io.savedata(filename,data,joiner) - local f = io.open(filename,"wb") + local f = open(filename,"wb") if f then if type(data) == "table" then f:write(concat(data,joiner or "")) @@ -80,7 +158,7 @@ function io.savedata(filename,data,joiner) f:write(data or "") end f:close() - io.flush() + flush() return true else return false @@ -89,36 +167,74 @@ end -- we can also chunk this one if needed: io.lines(filename,chunksize,"*l") -function io.loadlines(filename,n) -- return nil if empty - local f = io.open(filename,'r') - if not f then - -- no file - elseif n then - local lines = { } - for i=1,n do - local line = f:read("*lines") - if line then - lines[#lines+1] = line - else - break +-- ffi.readline + +if fio and fio.readline then + + local readline = fio.readline + + function io.loadlines(filename,n) -- return nil if empty + local f = open(filename,'r') + if not f then + -- no file + elseif n then + local lines = { } + for i=1,n do + local line = readline(f) + if line then + lines[i] = line + else + break + end + end + f:close() + lines = concat(lines,"\n") + if #lines > 0 then + return lines + end + else + local line = readline(f) + f:close() + if line and #line > 0 then + return line end end - f:close() - lines = concat(lines,"\n") - if #lines > 0 then - return lines - end - else - local line = f:read("*line") or "" - f:close() - if #line > 0 then - return line + end + +else + + function io.loadlines(filename,n) -- return nil if empty + local f = open(filename,'r') + if not f then + -- no file + elseif n then + local lines = { } + for i=1,n do + local line = f:read("*lines") + if line then + lines[i] = line + else + break + end + end + f:close() + lines = concat(lines,"\n") + if #lines > 0 then + return lines + end + else + local line = f:read("*line") or "" + f:close() + if #line > 0 then + return line + end end end + end function io.loadchunk(filename,n) - local f = io.open(filename,'rb') + local f = open(filename,'rb') if f then local data = f:read(n or 1024) f:close() @@ -129,7 +245,7 @@ function io.loadchunk(filename,n) end function io.exists(filename) - local f = io.open(filename) + local f = open(filename) if f == nil then return false else @@ -139,7 +255,7 @@ function io.exists(filename) end function io.size(filename) - local f = io.open(filename) + local f = open(filename) if f == nil then return 0 else @@ -149,17 +265,18 @@ function io.size(filename) end end -function io.noflines(f) +local function noflines(f) if type(f) == "string" then - local f = io.open(filename) + local f = open(filename) if f then - local n = f and io.noflines(f) or 0 + local n = f and noflines(f) or 0 f:close() return n else return 0 end else + -- todo: load and lpeg local n = 0 for _ in f:lines() do n = n + 1 @@ -169,6 +286,10 @@ function io.noflines(f) end end +io.noflines = noflines + +-- inlined is faster ... beware, better use util-fil + local nextchar = { [ 4] = function(f) return f:read(1,1,1,1) @@ -250,16 +371,16 @@ end function io.ask(question,default,options) while true do - io.write(question) + write(question) if options then - io.write(format(" [%s]",concat(options,"|"))) + write(format(" [%s]",concat(options,"|"))) end if default then - io.write(format(" [%s]",default)) + write(format(" [%s]",default)) end - io.write(format(" ")) - io.flush() - local answer = io.read() + write(format(" ")) + flush() + local answer = read() answer = gsub(answer,"^%s*(.*)%s*$","%1") if answer == "" and default then return default @@ -282,7 +403,7 @@ function io.ask(question,default,options) end end -local function readnumber(f,n,m) +local function readnumber(f,n,m) -- to be replaced if m then f:seek("set",n) n = m @@ -291,38 +412,32 @@ local function readnumber(f,n,m) return byte(f:read(1)) elseif n == 2 then local a, b = byte(f:read(2),1,2) - return 256 * a + b + return 0x100 * a + b elseif n == 3 then local a, b, c = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c + return 0x10000 * a + 0x100 * b + c elseif n == 4 then local a, b, c, d = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256 * c + d + return 0x1000000 * a + 0x10000 * b + 0x100 * c + d elseif n == 8 then local a, b = readnumber(f,4), readnumber(f,4) - return 256 * a + b + return 0x100 * a + b elseif n == 12 then local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4) - return 256*256 * a + 256 * b + c + return 0x10000 * a + 0x100 * b + c elseif n == -2 then local b, a = byte(f:read(2),1,2) - return 256*a + b + return 0x100 * a + b elseif n == -3 then local c, b, a = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c + return 0x10000 * a + 0x100 * b + c elseif n == -4 then local d, c, b, a = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256*c + d + return 0x1000000 * a + 0x10000 * b + 0x100*c + d elseif n == -8 then local h, g, f, e, d, c, b, a = byte(f:read(8),1,8) - return 256*256*256*256*256*256*256 * a + - 256*256*256*256*256*256 * b + - 256*256*256*256*256 * c + - 256*256*256*256 * d + - 256*256*256 * e + - 256*256 * f + - 256 * g + - h + return 0x100000000000000 * a + 0x1000000000000 * b + 0x10000000000 * c + 0x100000000 * d + + 0x1000000 * e + 0x10000 * f + 0x100 * g + h else return 0 end |