"Fossies" - the Fresh Open Source Software Archive 
Member "seed7/lib/strifile.s7i" (7 Jul 2020, 9730 Bytes) of package /linux/misc/seed7_05_20210223.tgz:
As a special service "Fossies" has tried to format the requested text file into HTML format (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1
2 (********************************************************************)
3 (* *)
4 (* strifile.s7i Implementation type for files stored in a string *)
5 (* Copyright (C) 2008 Thomas Mertes *)
6 (* *)
7 (* This file is part of the Seed7 Runtime Library. *)
8 (* *)
9 (* The Seed7 Runtime Library is free software; you can *)
10 (* redistribute it and/or modify it under the terms of the GNU *)
11 (* Lesser General Public License as published by the Free Software *)
12 (* Foundation; either version 2.1 of the License, or (at your *)
13 (* option) any later version. *)
14 (* *)
15 (* The Seed7 Runtime Library is distributed in the hope that it *)
16 (* will be useful, but WITHOUT ANY WARRANTY; without even the *)
17 (* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *)
18 (* PURPOSE. See the GNU Lesser General Public License for more *)
19 (* details. *)
20 (* *)
21 (* You should have received a copy of the GNU Lesser General *)
22 (* Public License along with this program; if not, write to the *)
23 (* Free Software Foundation, Inc., 51 Franklin Street, *)
24 (* Fifth Floor, Boston, MA 02110-1301, USA. *)
25 (* *)
26 (********************************************************************)
27
28
29 (**
30 * [[file|File]] implementation type for files stored in a [[string]].
31 *)
32 const type: strifile is sub null_file struct
33 var string: content is "";
34 var integer: position is 1;
35 end struct;
36
37 type_implements_interface(strifile, file);
38
39
40 (**
41 * Open a ''strifile'' with the given string content.
42 * @return the file opened.
43 *)
44 const func file: openStrifile (in string: content) is func
45 result
46 var file: newFile is STD_NULL;
47 local
48 var strifile: new_strifile is strifile.value;
49 begin
50 new_strifile.content := content;
51 newFile := toInterface(new_strifile);
52 end func;
53
54
55 (**
56 * Open a ''strifile'' with an empty string content.
57 * @return the file opened.
58 *)
59 const func file: openStrifile is func
60 result
61 var file: newFile is STD_NULL;
62 local
63 var strifile: new_strifile is strifile.value;
64 begin
65 newFile := toInterface(new_strifile);
66 end func;
67
68
69 (**
70 * Write the [[string]] ''stri'' to ''outStrifile''.
71 *)
72 const proc: write (inout strifile: outStrifile, in string: stri) is func
73 begin
74 if outStrifile.position = succ(length(outStrifile.content)) then
75 outStrifile.content &:= stri;
76 elsif outStrifile.position <= length(outStrifile.content) then
77 if pred(outStrifile.position) <= length(outStrifile.content) - length(stri) then
78 outStrifile.content @:= [outStrifile.position] stri;
79 else
80 outStrifile.content := outStrifile.content[.. pred(outStrifile.position)];
81 outStrifile.content &:= stri;
82 end if;
83 elsif outStrifile.position > length(outStrifile.content) then
84 outStrifile.content &:=
85 "\0;" mult pred(outStrifile.position - length(outStrifile.content)) &
86 stri;
87 end if;
88 outStrifile.position +:= length(stri);
89 end func;
90
91
92 const proc: moveLeft (inout strifile: outStrifile, in string: stri) is func
93 begin
94 if outStrifile.position > length(stri) then
95 outStrifile.position -:= length(stri);
96 else
97 outStrifile.position := 1;
98 end if;
99 end func;
100
101
102 (**
103 * Read a character from ''inStrifile''.
104 * @return the character read, or [[char#EOF|EOF]] at the end of the file.
105 *)
106 const func char: getc (inout strifile: inStrifile) is func
107 result
108 var char: charRead is ' ';
109 begin
110 if inStrifile.position <= length(inStrifile.content) then
111 charRead := inStrifile.content[inStrifile.position];
112 incr(inStrifile.position);
113 else
114 charRead := EOF;
115 end if;
116 end func;
117
118
119 (**
120 * Read a [[string]] with maximum length from ''inStrifile''.
121 * @return the string read.
122 * @exception RANGE_ERROR The parameter ''maxLength'' is negative.
123 *)
124 const func string: gets (inout strifile: inStrifile, in integer: maxLength) is func
125 result
126 var string: striRead is "";
127 begin
128 if maxLength < 0 then
129 raise RANGE_ERROR;
130 elsif maxLength <= succ(length(inStrifile.content) - inStrifile.position) then
131 striRead := inStrifile.content[inStrifile.position len maxLength];
132 inStrifile.position +:= maxLength;
133 else
134 striRead := inStrifile.content[inStrifile.position ..];
135 inStrifile.position := succ(length(inStrifile.content));
136 end if;
137 end func;
138
139
140 (**
141 * Read a word from ''inStrifile''.
142 * Before reading the word it skips spaces and tabs. The function
143 * accepts words ending with " ", "\t", "\n", or [[char#EOF|EOF]].
144 * The word ending characters are not copied into the string.
145 * When the function is left inStrifile.bufferChar contains ' ',
146 * '\t', '\n' or [[char#EOF|EOF]].
147 * @return the word read.
148 *)
149 const func string: getwd (inout strifile: inStrifile) is func
150 result
151 var string: stri is "";
152 local
153 const set of char: space_or_tab is {' ', '\t'};
154 const set of char: space_tab_or_nl is {' ', '\t', '\n'};
155 var integer: wordStartPos is 0;
156 var integer: wordEndPos is 0;
157 begin
158 wordStartPos := inStrifile.position;
159 while wordStartPos <= length(inStrifile.content) and
160 inStrifile.content[wordStartPos] in space_or_tab do
161 incr(wordStartPos);
162 end while;
163 if wordStartPos > length(inStrifile.content) then
164 inStrifile.position := wordStartPos;
165 inStrifile.bufferChar := EOF;
166 else
167 wordEndPos := succ(wordStartPos);
168 while wordEndPos <= length(inStrifile.content) and
169 inStrifile.content[wordEndPos] not in space_tab_or_nl do
170 incr(wordEndPos);
171 end while;
172 if wordEndPos <= length(inStrifile.content) then
173 stri := inStrifile.content[wordStartPos .. pred(wordEndPos)];
174 inStrifile.position := succ(wordEndPos);
175 inStrifile.bufferChar := inStrifile.content[wordEndPos];
176 else
177 stri := inStrifile.content[wordStartPos ..];
178 inStrifile.position := succ(length(inStrifile.content));
179 inStrifile.bufferChar := EOF;
180 end if;
181 end if;
182 end func;
183
184
185 (**
186 * Read a line from ''inStrifile''.
187 * A strifile works as if all lines end with '\n'.
188 * The line ending character is not copied into the string. When
189 * the function is left inStrifile.bufferChar contains '\n' or
190 * [[char#EOF|EOF]].
191 * @return the line read.
192 *)
193 const func string: getln (inout strifile: inStrifile) is func
194 result
195 var string: stri is "";
196 local
197 var integer: newlinePos is 0;
198 begin
199 newlinePos := pos(inStrifile.content, '\n', inStrifile.position);
200 if newlinePos <> 0 then
201 stri := inStrifile.content[inStrifile.position .. pred(newlinePos)];
202 inStrifile.position := succ(newlinePos);
203 inStrifile.bufferChar := '\n';
204 else
205 stri := inStrifile.content[inStrifile.position ..];
206 inStrifile.position := succ(length(inStrifile.content));
207 inStrifile.bufferChar := EOF;
208 end if;
209 end func;
210
211
212 (**
213 * Determine the end-of-file indicator.
214 * The end-of-file indicator is set if at least one request to read
215 * from the file failed.
216 * @return TRUE if the end-of-file indicator is set, FALSE otherwise.
217 *)
218 const func boolean: eof (in strifile: inStrifile) is
219 return inStrifile.position > length(inStrifile.content);
220
221
222 (**
223 * Determine if at least one character can be read successfully.
224 * This function allows a file to be handled like an iterator.
225 * @return FALSE if ''getc'' would return [[char#EOF|EOF]],
226 * TRUE otherwise.
227 *)
228 const func boolean: hasNext (in strifile: inStrifile) is
229 return inStrifile.position <= length(inStrifile.content);
230
231
232 (**
233 * Obtain the length of a ''aStrifile''.
234 * The file length is measured in characters.
235 * @return the length of a file.
236 *)
237 const func integer: length (in strifile: aStrifile) is
238 return length(aStrifile.content);
239
240
241 (**
242 * Truncate ''aStrifile'' to the given ''length''.
243 * If the file previously was larger than ''length'', the extra data is lost.
244 * If the file previously was shorter, it is extended, and the extended
245 * part is filled with null bytes ('\0;').
246 * The file length is measured in characters.
247 *)
248 const proc: truncate (inout strifile: aStrifile, in integer: length) is func
249 begin
250 if length < 0 then
251 raise RANGE_ERROR;
252 elsif length(aStrifile.content) > length then
253 aStrifile.content := aStrifile.content[.. length];
254 elsif length(aStrifile.content) < length then
255 aStrifile.content := aStrifile.content &
256 "\0;" mult (length - length(aStrifile.content));
257 end if;
258 end func;
259
260
261 (**
262 * Set the current file position.
263 * The file position is measured in characters from the start of the file.
264 * The first character in the file has the position 1.
265 *)
266 const proc: seek (inout strifile: aStrifile, in integer: position) is func
267 begin
268 aStrifile.position := position;
269 end func;
270
271
272 (**
273 * Obtain the current file position of ''aStrifile''.
274 * The file position is measured in characters from the start of the file.
275 * The first character in the file has the position 1.
276 * @return the current file position.
277 *)
278 const func integer: tell (in strifile: aStrifile) is
279 return aStrifile.position;