1
2
3
4
5
6
7
8
9
10
11 container resources [
12 lock:bool
13 data:&:@:resource
14 ]
15
16 container resource [
17 name:text
18 contents:text
19 ]
20
21 def start-reading resources:&:resources, filename:text -> contents:&:source:char, error?:bool [
22 local-scope
23 load-ingredients
24 error? <- copy 0/false
25 {
26 ¦ break-unless resources
27 ¦
28 ¦ contents, error? <- start-reading-from-fake-resource resources, filename
29 ¦ return
30 }
31
32 file:num <- $open-file-for-reading filename
33 return-unless file, 0/contents, 1/error?
34 contents:&:source:char, sink:&:sink:char <- new-channel 30
35 start-running receive-from-file file, sink
36 ]
37
38 def slurp resources:&:resources, filename:text -> contents:text, error?:bool [
39 local-scope
40 load-ingredients
41 source:&:source:char, error?:bool <- start-reading resources, filename
42 return-if error?, 0/contents
43 buf:&:buffer:char <- new-buffer 30/capacity
44 {
45 ¦ c:char, done?:bool, source <- read source
46 ¦ break-if done?
47 ¦ buf <- append buf, c
48 ¦ loop
49 }
50 contents <- buffer-to-array buf
51 ]
52
53 def start-reading-from-fake-resource resources:&:resources, resource:text -> contents:&:source:char, error?:bool [
54 local-scope
55 load-ingredients
56 error? <- copy 0/no-error
57 i:num <- copy 0
58 data:&:@:resource <- get *resources, data:offset
59 len:num <- length *data
60 {
61 ¦ done?:bool <- greater-or-equal i, len
62 ¦ break-if done?
63 ¦ tmp:resource <- index *data, i
64 ¦ i <- add i, 1
65 ¦ curr-resource:text <- get tmp, name:offset
66 ¦ found?:bool <- equal resource, curr-resource
67 ¦ loop-unless found?
68 ¦ contents:&:source:char, sink:&:sink:char <- new-channel 30
69 ¦ curr-contents:text <- get tmp, contents:offset
70 ¦ start-running receive-from-text curr-contents, sink
71 ¦ return
72 }
73 return 0/not-found, 1/error
74 ]
75
76 def receive-from-file file:num, sink:&:sink:char -> sink:&:sink:char [
77 local-scope
78 load-ingredients
79 {
80 ¦ c:char, eof?:bool <- $read-from-file file
81 ¦ break-if eof?
82 ¦ sink <- write sink, c
83 ¦ loop
84 }
85 sink <- close sink
86 file <- $close-file file
87 ]
88
89 def receive-from-text contents:text, sink:&:sink:char -> sink:&:sink:char [
90 local-scope
91 load-ingredients
92 i:num <- copy 0
93 len:num <- length *contents
94 {
95 ¦ done?:bool <- greater-or-equal i, len
96 ¦ break-if done?
97 ¦ c:char <- index *contents, i
98 ¦ sink <- write sink, c
99 ¦ i <- add i, 1
100 ¦ loop
101 }
102 sink <- close sink
103 ]
104
105 def start-writing resources:&:resources, filename:text -> sink:&:sink:char, routine-id:num, error?:bool [
106 local-scope
107 load-ingredients
108 error? <- copy 0/false
109 source:&:source:char, sink:&:sink:char <- new-channel 30
110 {
111 ¦ break-unless resources
112 ¦
113 ¦ routine-id <- start-running transmit-to-fake-resource resources, filename, source
114 ¦ return
115 }
116
117 file:num <- $open-file-for-writing filename
118 return-unless file, 0/sink, 0/routine-id, 1/error?
119 {
120 ¦ break-if file
121 ¦ msg:text <- append [no such file: ] filename
122 ¦ assert file, msg
123 }
124 routine-id <- start-running transmit-to-file file, source
125 ]
126
127 def dump resources:&:resources, filename:text, contents:text -> resources:&:resources, error?:bool [
128 local-scope
129 load-ingredients
130
131 return-unless contents, resources, 0/no-error
132 sink-file:&:sink:char, write-routine:num, error?:bool <- start-writing resources, filename
133 return-if error?
134 i:num <- copy 0
135 len:num <- length *contents
136 {
137 ¦ done?:bool <- greater-or-equal i, len
138 ¦ break-if done?
139 ¦ c:char <- index *contents, i
140 ¦ sink-file <- write sink-file, c
141 ¦ i <- add i, 1
142 ¦ loop
143 }
144 close sink-file
145
146
147 wait-for-routine write-routine
148 ]
149
150 def transmit-to-file file:num, source:&:source:char -> source:&:source:char [
151 local-scope
152 load-ingredients
153 {
154 ¦ c:char, done?:bool, source <- read source
155 ¦ break-if done?
156 ¦ $write-to-file file, c
157 ¦ loop
158 }
159 file <- $close-file file
160 ]
161
162 def transmit-to-fake-resource resources:&:resources, filename:text, source:&:source:char -> resources:&:resources, source:&:source:char [
163 local-scope
164 load-ingredients
165 lock:location <- get-location *resources, lock:offset
166 wait-for-reset-then-set lock
167
168 buf:&:buffer:char <- new-buffer 30
169 {
170 ¦ c:char, done?:bool, source <- read source
171 ¦ break-if done?
172 ¦ buf <- append buf, c
173 ¦ loop
174 }
175 contents:text <- buffer-to-array buf
176 new-resource:resource <- merge filename, contents
177
178 curr-filename:text <- copy 0
179 data:&:@:resource <- get *resources, data:offset
180
181 i:num <- copy 0
182 len:num <- length *data
183 {
184 ¦ done?:bool <- greater-or-equal i, len
185 ¦ break-if done?
186 ¦ tmp:resource <- index *data, i
187 ¦ curr-filename <- get tmp, name:offset
188 ¦ found?:bool <- equal filename, curr-filename
189 ¦ {
190 ¦ ¦ break-unless found?
191 ¦ ¦ put-index *data, i, new-resource
192 ¦ ¦ jump +unlock-and-exit
193 ¦ }
194 ¦ i <- add i, 1
195 ¦ loop
196 }
197
198 new-len:num <- add len, 1
199 new-data:&:@:resource <- new resource:type, new-len
200 put *resources, data:offset, new-data
201
202 i:num <- copy 0
203 {
204 ¦ done?:bool <- greater-or-equal i, len
205 ¦ break-if done?
206 ¦ tmp:resource <- index *data, i
207 ¦ put-index *new-data, i, tmp
208 }
209
210 put-index *new-data, len, new-resource
211 +unlock-and-exit
212 reset lock
213 ]