data-fil.lua /size: 4365 b    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['data-fil'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local ioopen = io.open
10local isdir = lfs.isdir
11
12local trace_locating = false  trackers.register("resolvers.locating", function(v) trace_locating = v end)
13
14local report_files = logs.reporter("resolvers","files")
15
16local resolvers        = resolvers
17local resolveprefix    = resolvers.resolve
18local findfile         = resolvers.findfile
19local scanfiles        = resolvers.scanfiles
20local registerfilehash = resolvers.registerfilehash
21local appendhash       = resolvers.appendhash
22
23local loadcachecontent = caches.loadcontent
24
25----- checkgarbage     = utilities.garbagecollector and utilities.garbagecollector.check
26
27function resolvers.locators.file(specification)
28    local filename = specification.filename
29    local realname = resolveprefix(filename) -- no shortcut
30    if realname and realname ~= '' and isdir(realname) then
31        if trace_locating then
32            report_files("file locator %a found as %a",filename,realname)
33        end
34        appendhash('file',filename,true) -- cache
35    elseif trace_locating then
36        report_files("file locator %a not found",filename)
37    end
38end
39
40function resolvers.hashers.file(specification)
41    local pathname = specification.filename
42    local content  = loadcachecontent(pathname,'files')
43    registerfilehash(pathname,content,content==nil)
44end
45
46function resolvers.generators.file(specification)
47    local pathname = specification.filename
48    local content  = scanfiles(pathname,false,true) -- scan once
49    registerfilehash(pathname,content,true)
50end
51
52resolvers.concatinators.file = file.join
53
54local finders  = resolvers.finders
55local notfound = finders.notfound
56
57function finders.file(specification,filetype)
58    local filename  = specification.filename
59    local foundname = findfile(filename,filetype)
60    if foundname and foundname ~= "" then
61        if trace_locating then
62            report_files("file finder: %a found",filename)
63        end
64        return foundname
65    else
66        if trace_locating then
67            report_files("file finder: %a not found",filename)
68        end
69        return notfound()
70    end
71end
72
73-- The default textopener will be overloaded later on.
74
75local openers    = resolvers.openers
76local notfound   = openers.notfound
77local overloaded = false
78
79local function textopener(tag,filename,f)
80    return {
81        reader = function() return f:read () end,
82        close  = function() return f:close() end,
83    }
84end
85
86function openers.helpers.textopener(...)
87    return textopener(...)
88end
89
90function openers.helpers.settextopener(opener)
91    if overloaded then
92        report_files("file opener: %s overloaded","already")
93    else
94        if trace_locating then
95            report_files("file opener: %s overloaded","once")
96        end
97        overloaded = true
98        textopener = opener
99    end
100end
101
102function openers.file(specification,filetype)
103    local filename = specification.filename
104    if filename and filename ~= "" then
105        local f = ioopen(filename,"r")
106        if f then
107            if trace_locating then
108                report_files("file opener: %a opened",filename)
109            end
110            return textopener("file",filename,f)
111        end
112    end
113    if trace_locating then
114        report_files("file opener: %a not found",filename)
115    end
116    return notfound()
117end
118
119local loaders  = resolvers.loaders
120local notfound = loaders.notfound
121
122function loaders.file(specification,filetype)
123    local filename = specification.filename
124    if filename and filename ~= "" then
125        local f = ioopen(filename,"rb")
126        if f then
127            if trace_locating then
128                report_files("file loader: %a loaded",filename)
129            end
130            local s = f:read("*a") -- io.readall(f) is faster but we never have large files here
131         -- if checkgarbage then
132         --     checkgarbage(#s)
133         -- end
134            f:close()
135            if s then
136                return true, s, #s
137            end
138        end
139    end
140    if trace_locating then
141        report_files("file loader: %a not found",filename)
142    end
143    return notfound()
144end
145