diff options
Diffstat (limited to 'tex/context/base/mkiv/data-tre.lua')
-rw-r--r-- | tex/context/base/mkiv/data-tre.lua | 355 |
1 files changed, 203 insertions, 152 deletions
diff --git a/tex/context/base/mkiv/data-tre.lua b/tex/context/base/mkiv/data-tre.lua index c4d43e3eb..da3d1f14f 100644 --- a/tex/context/base/mkiv/data-tre.lua +++ b/tex/context/base/mkiv/data-tre.lua @@ -6,6 +6,10 @@ if not modules then modules = { } end modules ['data-tre'] = { license = "see context related readme files" } +-- A tree search is rather dumb ... there is some basic caching of searched trees +-- but nothing is cached over runs ... it's also a wildcard one so we cannot use +-- the normal scanner. + -- tree://e:/temporary/mb-mp/**/drawing.jpg -- tree://e:/temporary/mb-mp/**/Drawing.jpg -- tree://t:./**/tufte.tex @@ -28,83 +32,119 @@ local trace_locating = false trackers.register("resolvers.locating", function(v local report_trees = logs.reporter("resolvers","trees") -local resolvers = resolvers -local resolveprefix = resolvers.resolve -local notfound = resolvers.finders.notfound -local lookup = resolvers.get_from_content +local resolvers = resolvers +local finders = resolvers.finders +local openers = resolvers.openers +local loaders = resolvers.loaders +local locators = resolvers.locators +local hashers = resolvers.hashers +local generators = resolvers.generators --- A tree search is rather dumb ... there is some basic caching of searched trees --- but nothing is cached over runs ... it's also a wildcard one so we cannot use --- the normal scanner. +do -local collectors = { } -local found = { } - -function resolvers.finders.tree(specification) -- to be adapted to new formats - local spec = specification.filename - local okay = found[spec] - if okay == nil then - if spec ~= "" then - local path = dirname(spec) - local name = basename(spec) - if path == "" then - path = "." - end - local names = collectors[path] - if not names then - local pattern = find(path,"/%*+$") and path or (path .. "/*") - names = globdir(pattern) - collectors[path] = names - end - local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$" - for i=1,#names do - local fullname = names[i] - if find(fullname,pattern) then - found[spec] = fullname - return fullname + local collectors = { } + local found = { } + local notfound = finders.notfound + + function finders.tree(specification) -- to be adapted to new formats + local spec = specification.filename + local okay = found[spec] + if okay == nil then + if spec ~= "" then + local path = dirname(spec) + local name = basename(spec) + if path == "" then + path = "." end - end - -- let's be nice: - local pattern = lower(pattern) - for i=1,#names do - local fullname = lower(names[i]) - if find(fullname,pattern) then - if isfile(fullname) then + local names = collectors[path] + if not names then + local pattern = find(path,"/%*+$") and path or (path .. "/*") + names = globdir(pattern) + collectors[path] = names + end + local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$" + for i=1,#names do + local fullname = names[i] + if find(fullname,pattern) then found[spec] = fullname return fullname - else - -- no os name mapping - break + end + end + -- let's be nice: + local pattern = lower(pattern) + for i=1,#names do + local fullname = lower(names[i]) + if find(fullname,pattern) then + if isfile(fullname) then + found[spec] = fullname + return fullname + else + -- no os name mapping + break + end end end end + okay = notfound() -- false + found[spec] = okay end - okay = notfound() -- false - found[spec] = okay + return okay end - return okay + end -function resolvers.locators.tree(specification) - local name = specification.filename - local realname = resolveprefix(name) -- no shortcut - if realname and realname ~= '' and isdir(realname) then - if trace_locating then - report_trees("locator %a found",realname) +do + + local resolveprefix = resolvers.resolve + local appendhash = resolvers.appendhash + + local function dolocate(specification) + local name = specification.filename + local realname = resolveprefix(name) -- no shortcut + if realname and realname ~= '' and isdir(realname) then + if trace_locating then + report_trees("locator %a found",realname) + end + appendhash('tree',name,false) -- don't cache + elseif trace_locating then + report_trees("locator %a not found",name) end - resolvers.appendhash('tree',name,false) -- don't cache - elseif trace_locating then - report_trees("locator %a not found",name) end + + locators.tree = dolocate + locators.dirlist = dolocate + locators.dirfile = dolocate + end -function resolvers.hashers.tree(specification) - local name = specification.filename - if trace_locating then - report_trees("analyzing %a",name) + +do + + local filegenerator = generators.file + + generators.dirlist = filegenerator + generators.dirfile = filegenerator + +end + +do + + local filegenerator = generators.file + local methodhandler = resolvers.methodhandler + + local function dohash(specification) + local name = specification.filename + if trace_locating then + report_trees("analyzing %a",name) + end + methodhandler("hashers",name) + filegenerator(specification) end - resolvers.methodhandler("hashers",name) - resolvers.generators.file(specification) + + hashers.tree = dohash + hashers.dirlist = dohash + hashers.dirfile = dohash + end -- This is a variation on tree lookups but this time we do cache in the given @@ -112,120 +152,131 @@ end -- for instance trees with 50K xml files plus a similar amount of resources to -- deal and we don't want too much overhead. -local collectors = { } -local splitter = lpeg.splitat("/**/") -local stripper = lpeg.replacer { [P("/") * P("*")^1 * P(-1)] = "" } - -table.setmetatableindex(collectors, function(t,k) - local rootname = lpegmatch(stripper,k) - local dataname = joinname(rootname,"dirlist") - local content = caches.loadcontent(dataname,"files",dataname) - if not content then - -- path branch usecache onlyonce tolerant - content = resolvers.scanfiles(rootname,nil,nil,false,true) -- so we accept crap - caches.savecontent(dataname,"files",content,dataname) - end - t[k] = content - return content -end) +local resolve do + + local collectors = { } + local splitter = lpeg.splitat("/**/") + local stripper = lpeg.replacer { [P("/") * P("*")^1 * P(-1)] = "" } + + local loadcontent = caches.loadcontent + local savecontent = caches.savecontent + + local notfound = finders.notfound + local scanfiles = resolvers.scanfiles + local lookup = resolvers.get_from_content -local function checked(root,p,n) - if p then - if type(p) == "table" then - for i=1,#p do - local fullname = joinname(root,p[i],n) + table.setmetatableindex(collectors, function(t,k) + local rootname = lpegmatch(stripper,k) + local dataname = joinname(rootname,"dirlist") + local content = loadcontent(dataname,"files",dataname) + if not content then + -- path branch usecache onlyonce tolerant + content = scanfiles(rootname,nil,nil,false,true) -- so we accept crap + savecontent(dataname,"files",content,dataname) + end + t[k] = content + return content + end) + + local function checked(root,p,n) + if p then + if type(p) == "table" then + for i=1,#p do + local fullname = joinname(root,p[i],n) + if isfile(fullname) then -- safeguard + return fullname + end + end + else + local fullname = joinname(root,p,n) if isfile(fullname) then -- safeguard return fullname end end - else - local fullname = joinname(root,p,n) - if isfile(fullname) then -- safeguard - return fullname - end end + return notfound() end - return notfound() -end --- no funny characters in path but in filename permitted .. sigh - -local function resolve(specification) -- can be called directly too - local filename = specification.filename - -- inspect(specification) - if filename ~= "" then - local root, rest = lpegmatch(splitter,filename) - if root and rest then - local path, name = dirname(rest), basename(rest) - if name ~= rest then - local content = collectors[root] - local p, n = lookup(content,name) - if not p then - return notfound() - end - local pattern = ".*/" .. path .. "$" - local istable = type(p) == "table" - if istable then - for i=1,#p do - local pi = p[i] - if pi == path or find(pi,pattern) then - local fullname = joinname(root,pi,n) - if isfile(fullname) then -- safeguard - return fullname + -- no funny characters in path but in filename permitted .. sigh + + resolve = function(specification) -- can be called directly too + local filename = specification.filename + -- inspect(specification) + if filename ~= "" then + local root, rest = lpegmatch(splitter,filename) + if root and rest then + local path, name = dirname(rest), basename(rest) + if name ~= rest then + local content = collectors[root] + local p, n = lookup(content,name) + if not p then + return notfound() + end + local pattern = ".*/" .. path .. "$" + local istable = type(p) == "table" + if istable then + for i=1,#p do + local pi = p[i] + if pi == path or find(pi,pattern) then + local fullname = joinname(root,pi,n) + if isfile(fullname) then -- safeguard + return fullname + end end end + elseif p == path or find(p,pattern) then + local fullname = joinname(root,p,n) + if isfile(fullname) then -- safeguard + return fullname + end end - elseif p == path or find(p,pattern) then - local fullname = joinname(root,p,n) - if isfile(fullname) then -- safeguard - return fullname + local queries = specification.queries + if queries and queries.option == "fileonly" then + return checked(root,p,n) + else + return notfound() end end - local queries = specification.queries - if queries and queries.option == "fileonly" then - return checked(root,p,n) - else - return notfound() - end + end + local path = dirname(filename) + local name = basename(filename) + local root = lpegmatch(stripper,path) + local content = collectors[path] + local p, n = lookup(content,name) + if p then + return checked(root,p,n) end end - local path, name = dirname(filename), basename(filename) - local root = lpegmatch(stripper,path) - local content = collectors[path] - local p, n = lookup(content,name) - if p then - return checked(root,p,n) - end + return notfound() end - return notfound() -end -resolvers.finders .dirlist = resolve -resolvers.locators .dirlist = resolvers.locators .tree -resolvers.hashers .dirlist = resolvers.hashers .tree -resolvers.generators.dirlist = resolvers.generators.file -resolvers.openers .dirlist = resolvers.openers .file -resolvers.loaders .dirlist = resolvers.loaders .file - -function resolvers.finders.dirfile(specification) - local queries = specification.queries - if queries then - queries.option = "fileonly" - else - specification.queries = { option = "fileonly" } + finders.dirlist = resolve + + function finders.dirfile(specification) + local queries = specification.queries + if queries then + queries.option = "fileonly" + else + specification.queries = { option = "fileonly" } + end + return resolve(specification) end - return resolve(specification) + end -resolvers.locators .dirfile = resolvers.locators .dirlist -resolvers.hashers .dirfile = resolvers.hashers .dirlist -resolvers.generators.dirfile = resolvers.generators.dirlist -resolvers.openers .dirfile = resolvers.openers .dirlist -resolvers.loaders .dirfile = resolvers.loaders .dirlist +do --- local locate = collectors[ [[E:\temporary\mb-mp]] ] --- local locate = collectors( [[\\storage-2\resources\mb-mp]] ) + local fileopener = openers.file + local fileloader = loaders.file + + openers.dirlist = fileopener + loaders.dirlist = fileloader + + openers.dirfile = fileopener + loaders.dirfile = fileloader + +end -- print(resolvers.findtexfile("tree://e:/temporary/mb-mp/**/VB_wmf_03_vw_01d_ant.jpg")) -- print(resolvers.findtexfile("tree://t:/**/tufte.tex")) |