36
37:- module('$rc',
38 [ open_resource/2, 39 open_resource/3, 40 current_resource/2 41 ]). 42
43:- meta_predicate
44 open_resource(:, -),
45 open_resource(:, -, +),
46 current_resource(:, ?). 47
48:- dynamic
49 user:resource/2,
50 user:resource/3. 51:- multifile
52 user:resource/2,
53 user:resource/3. 54
60
61open_resource(Name, Handle) :-
62 open_resource(Name, Handle, []).
63
64open_resource(Module:RcName, Stream, Options) :-
65 is_list(Options),
66 !,
67 ( default_module(Module, RModule),
68 current_resource(RModule:RcName, FileSpec)
69 -> absolute_file_name(FileSpec, File),
70 open(File, read, Stream, Options)
71 ; '$rc_handle'(Zipper),
72 zip_close(Zipper, Clone),
73 tag_rc_name(Module, RcName, TaggedName),
74 zipper_goto(Clone, file(TaggedName))
75 -> zipper_open_current(Clone, Stream,
76 [ release(true)
77 | Options
78 ]),
79 zip_close_(Clone, _)
80 ; '$existence_error'(resource, Module:RcName)
81 ).
82open_resource(Name, _Class, Stream) :-
83 open_resource(Name, Stream).
84
85tag_rc_name(user, RcName, RcName) :- !.
86tag_rc_name(Module, RcName, TaggedName) :-
87 atomic_list_concat([Module, ':', RcName], TaggedName).
88tag_rc_name(_, RcName, RcName).
89
94
95current_resource(M:Name, File) :-
96 current_module(M),
97 ( current_predicate(M:resource/2),
98 M:resource(Name, File)
99 ; current_predicate(M:resource/3),
100 M:resource(Name, _Class, File)
101 ).
102
106
107:- public c_open_resource/3. 108:- meta_predicate c_open_resource(:, +, -). 109
110c_open_resource(Name, Mode, Stream) :-
111 atom_chars(Mode, Chars),
112 ( Chars = [r|MChars]
113 -> mode_options(MChars, Options),
114 open_resource(Name, Stream, Options)
115 ; '$domain_error'(open_resource_mode, Mode)
116 ).
117
118mode_options([], []).
119mode_options([t|Chars], [type(text)|T]) :-
120 !,
121 mode_options(Chars, T).
122mode_options([b|Chars], [type(binary)|T]) :-
123 !,
124 mode_options(Chars, T).
125mode_options([_|Chars], T) :-
126 mode_options(Chars, T).
127
128
129 132
133:- register_iri_scheme(res, res_iri_hook, []). 134
140
141res_iri_hook(open(Mode,Options), IRI, Stream) :-
142 ( Mode == read
143 -> setup_call_cleanup(
144 iri_zipper(IRI, Zipper),
145 zipper_open_current(Zipper, Stream, Options),
146 zip_close_(Zipper, _))
147 ; '$permission_error'(open, source_sink, IRI)
148 ).
149res_iri_hook(access(Mode), IRI0, True) :-
150 ( read_mode(Mode),
151 '$absolute_file_name'(IRI0, Canonical0),
152 entry_name(Canonical0, Canonical),
153 iri_offset(Canonical, _Offset)
154 -> access_ok(Mode, Canonical, True)
155 ; True = false
156 ).
157res_iri_hook(time, IRI, Time) :-
158 setup_call_cleanup(
159 iri_zipper_ex(IRI, Zipper),
160 zipper_file_property(Zipper, _, time, Time),
161 zip_close_(Zipper, _)).
162res_iri_hook(size, IRI, Size) :-
163 setup_call_cleanup(
164 iri_zipper_ex(IRI, Zipper),
165 zipper_file_property(Zipper, _, size, Size),
166 zip_close_(Zipper, _)).
167
168read_mode(read).
169read_mode(exists).
170read_mode(file).
171read_mode(directory).
172
173entry_name(Entry, Entry).
174entry_name(Entry0, Entry) :-
175 \+ sub_atom(Entry0, _, _, 0, /),
176 atom_concat(Entry0, /, Entry).
177
178
182
183access_ok(directory, Entry, True) :-
184 !,
185 ( sub_atom(Entry, _, _, 0, /)
186 -> True = true
187 ; True = false
188 ).
189access_ok(file, Entry, True) :-
190 !,
191 ( sub_atom(Entry, _, _, 0, /)
192 -> True = false
193 ; True = true
194 ).
195access_ok(_, _, true).
196
201
202iri_zipper(IRI, Clone) :-
203 '$absolute_file_name'(IRI, Canonical),
204 iri_offset(Canonical, Offset),
205 '$rc_handle'(Zipper),
206 zip_clone(Zipper, Clone),
207 zipper_goto(Clone, offset(Offset)).
208
209iri_zipper_ex(IRI, Zipper) :-
210 iri_zipper(IRI, Zipper),
211 !.
212iri_zipper_ex(IRI, _Zipper) :-
213 '$existence_error'(source_sink, IRI).
214
218
219:- dynamic rc_index_db/2, rc_index_done/0. 220:- volatile rc_index_db/2, rc_index_done/0. 221
222iri_offset(Entry, Offset) :-
223 rc_index_done,
224 !,
225 rc_index_db(Entry, Offset).
226iri_offset(Entry, Offset) :-
227 with_mutex('$rc', index_rc),
228 !,
229 rc_index_db(Entry, Offset).
230
231index_rc :-
232 rc_index_done,
233 !.
234index_rc :-
235 '$rc_handle'(Zipper),
236 setup_call_cleanup(
237 zip_clone(Zipper, Clone),
238 ( zipper_goto(Clone, first),
239 index_rc(Clone)
240 ),
241 zip_close_(Clone, _)),
242 asserta(rc_index_done).
243
244index_rc(Zipper) :-
245 zipper_file_property(Zipper, Name, offset, Offset),
246 atom_concat('res://', Name, IRI),
247 assertz(rc_index_db(IRI, Offset)),
248 ( zipper_goto(Zipper, next)
249 -> index_rc(Zipper)
250 ; true
251 ).
252
253
255
256zipper_file_property(Zipper, Name, Prop, Value) :-
257 zip_file_info_(Zipper, Name, Info),
258 zip_prop_arg(Prop, Arg),
259 arg(Arg, Info, Value).
260
261zip_prop_arg(size, 2).
262zip_prop_arg(time, 5).
263zip_prop_arg(offset, 6)