Name | Executed | Routines | % | Executed | Lines | % | Unexecuted |
/home/matt/eu/rds/include/std/get.e | 15 | 16 | 93.75% | 217 | 295 | 73.56% | 78 |
Routine | Executed | Lines | Unexecuted | |
Get2() | 40 | 60 | 66.67% | 20 |
Get() | 37 | 55 | 67.27% | 18 |
get_qchar() | 0 | 15 | 0.00% | 15 |
read_comment() | 4 | 16 | 25.00% | 12 |
get_number() | 61 | 67 | 91.04% | 6 |
get_value() | 12 | 15 | 80.00% | 3 |
get_string() | 14 | 16 | 87.50% | 2 |
escape_char() | 4 | 5 | 80.00% | 1 |
get_ch() | 9 | 10 | 90.00% | 1 |
char() | 2 | 2 | 100.00% | 0 |
defaulted_value() | 7 | 7 | 100.00% | 0 |
get() | 2 | 2 | 100.00% | 0 |
natural() | 2 | 2 | 100.00% | 0 |
plus_or_minus() | 2 | 2 | 100.00% | 0 |
skip_blanks() | 5 | 5 | 100.00% | 0 |
value() | 2 | 2 | 100.00% | 0 |
# | Executed | |
1 | -- (c) Copyright - See License.txt | |
2 | -- | |
3 | namespace stdget | |
4 | ||
5 | include std/io.e | |
6 | include std/error.e | |
7 | ||
8 | --**** | |
9 | -- == Input Routines | |
10 | -- | |
11 | -- < | |
12 | -- | |
13 | -- | |
14 | ||
15 | --**** | |
16 | -- === Error Status Constants | |
17 | -- These are returned from [[:get]] and [[:value]]. | |
18 | ||
19 | public constant | |
20 | 101 | GET_SUCCESS = 0, |
21 | 101 | GET_EOF = -1, |
22 | 101 | GET_FAIL = 1, |
23 | 101 | GET_NOTHING = -2 |
24 | ||
25 | 101 | constant DIGITS = "0123456789", |
26 | 101 | HEX_DIGITS = DIGITS & "ABCDEF", |
27 | 101 | START_NUMERIC = DIGITS & "-+.#" |
28 | ||
29 | 101 | constant TRUE = 1 |
30 | ||
31 | 921 | |
32 | 921 | return x >= 0 |
33 | end type | |
34 | ||
35 | 1720 | |
36 | 1720 | return x >= -1 and x <= 255 |
37 | end type | |
38 | ||
39 | natural input_file -- file to be read from | |
40 | ||
41 | object input_string -- string to be read from | |
42 | natural string_next | |
43 | ||
44 | char ch -- the current character | |
45 | ||
46 | ||
47 | 1696 | |
48 | -- set ch to the next character in the input stream (either string or file) | |
49 | ||
50 | 1696 | if sequence(input_string) then |
51 | 539 | if string_next <= length(input_string) then |
52 | 445 | ch = input_string[string_next] |
53 | 445 | string_next += 1 |
54 | else | |
55 | 94 | ch = GET_EOF |
56 | end if | |
57 | else | |
58 | 1157 | ch = getc(input_file) |
59 | 1157 | if ch = GET_EOF then |
60 | 0 | string_next += 1 |
61 | end if | |
62 | end if | |
63 | 1696 | end procedure |
64 | ||
65 | 101 | constant white_space = " \t\n\r" |
66 | 72 | |
67 | -- skip white space | |
68 | -- ch is "live" at entry and exit | |
69 | ||
70 | 72 | while find(ch, white_space) do |
71 | 40 | get_ch() |
72 | 40 | end while |
73 | 72 | end procedure |
74 | ||
75 | 101 | constant ESCAPE_CHARS = "n'\"t\\r", |
76 | 101 | ESCAPED_CHARS = "\n'\"\t\\\r" |
77 | ||
78 | 12 | |
79 | -- return escape character | |
80 | natural i | |
81 | ||
82 | 12 | i = find(c, ESCAPE_CHARS) |
83 | 12 | if i = 0 then |
84 | 0 | return GET_FAIL |
85 | else | |
86 | 12 | return ESCAPED_CHARS[i] |
87 | end if | |
88 | end function | |
89 | ||
90 | 0 | |
91 | -- get a single-quoted character | |
92 | -- ch is "live" at exit | |
93 | char c | |
94 | ||
95 | 0 | get_ch() |
96 | 0 | c = ch |
97 | 0 | if ch = '\\' then |
98 | 0 | get_ch() |
99 | 0 | c = escape_char(ch) |
100 | 0 | if c = GET_FAIL then |
101 | 0 | return {GET_FAIL, 0} |
102 | end if | |
103 | 0 | elsif ch = '\'' then |
104 | 0 | return {GET_FAIL, 0} |
105 | end if | |
106 | 0 | get_ch() |
107 | 0 | if ch != '\'' then |
108 | 0 | return {GET_FAIL, 0} |
109 | else | |
110 | 0 | get_ch() |
111 | 0 | return {GET_SUCCESS, c} |
112 | end if | |
113 | end function | |
114 | ||
115 | 67 | |
116 | -- get a double-quoted character string | |
117 | -- ch is "live" at exit | |
118 | sequence text | |
119 | ||
120 | 67 | text = "" |
121 | 67 | while TRUE do |
122 | 1060 | get_ch() |
123 | 1060 | if ch = GET_EOF or ch = '\n' then |
124 | 0 | return {GET_FAIL, 0} |
125 | 1060 | elsif ch = '"' then |
126 | 67 | get_ch() |
127 | 67 | return {GET_SUCCESS, text} |
128 | 993 | elsif ch = '\\' then |
129 | 12 | get_ch() |
130 | 12 | ch = escape_char(ch) |
131 | 12 | if ch = GET_FAIL then |
132 | 0 | return {GET_FAIL, 0} |
133 | end if | |
134 | end if | |
135 | 993 | text = text & ch |
136 | 993 | end while |
137 | end function | |
138 | ||
139 | 85 | |
140 | 85 | return x = -1 or x = +1 |
141 | end type | |
142 | ||
143 | 101 | constant GET_IGNORE = GET_NOTHING |
144 | 1 | |
145 | 1 | if atom(input_string) then |
146 | 0 | while ch!='\n' and ch!='\r' and ch!=-1 do |
147 | 0 | get_ch() |
148 | 0 | end while |
149 | 0 | get_ch() |
150 | 0 | if ch=-1 then |
151 | 0 | return {GET_EOF, 0} |
152 | else | |
153 | 0 | return {GET_IGNORE, 0} |
154 | end if | |
155 | else | |
156 | 1 | for i=string_next to length(input_string) do |
157 | 0 | ch=input_string[i] |
158 | 0 | if ch='\n' or ch='\r' then |
159 | 0 | string_next=i+1 |
160 | 0 | return {GET_IGNORE, 0} |
161 | end if | |
162 | 0 | end for |
163 | 1 | return {GET_EOF, 0} |
164 | end if | |
165 | end function | |
166 | ||
167 | 79 | |
168 | -- read a number or a comment | |
169 | -- ch is "live" at entry and exit | |
170 | plus_or_minus sign, e_sign | |
171 | natural ndigits | |
172 | integer hex_digit | |
173 | atom mantissa, dec, e_mag | |
174 | ||
175 | 79 | sign = +1 |
176 | 79 | mantissa = 0 |
177 | 79 | ndigits = 0 |
178 | ||
179 | -- process sign | |
180 | 79 | if ch = '-' then |
181 | 1 | sign = -1 |
182 | 1 | get_ch() |
183 | 1 | if ch='-' then |
184 | 1 | return read_comment() |
185 | end if | |
186 | 78 | elsif ch = '+' then |
187 | 2 | get_ch() |
188 | end if | |
189 | ||
190 | -- get mantissa | |
191 | 78 | if ch = '#' then |
192 | -- process hex integer and return | |
193 | 6 | get_ch() |
194 | 6 | while TRUE do |
195 | 16 | hex_digit = find(ch, HEX_DIGITS)-1 |
196 | 16 | if hex_digit >= 0 then |
197 | 10 | ndigits += 1 |
198 | 10 | mantissa = mantissa * 16 + hex_digit |
199 | 10 | get_ch() |
200 | else | |
201 | 6 | if ndigits > 0 then |
202 | 5 | return {GET_SUCCESS, sign * mantissa} |
203 | else | |
204 | 1 | return {GET_FAIL, 0} |
205 | end if | |
206 | end if | |
207 | 10 | end while |
208 | end if | |
209 | ||
210 | -- decimal integer or floating point | |
211 | 72 | while ch >= '0' and ch <= '9' do |
212 | 157 | ndigits += 1 |
213 | 157 | mantissa = mantissa * 10 + (ch - '0') |
214 | 157 | get_ch() |
215 | 157 | end while |
216 | ||
217 | 72 | if ch = '.' then |
218 | -- get fraction | |
219 | 12 | get_ch() |
220 | 12 | dec = 10 |
221 | 12 | while ch >= '0' and ch <= '9' do |
222 | 16 | ndigits += 1 |
223 | 16 | mantissa += (ch - '0') / dec |
224 | 16 | dec *= 10 |
225 | 16 | get_ch() |
226 | 16 | end while |
227 | end if | |
228 | ||
229 | 72 | if ndigits = 0 then |
230 | 1 | return {GET_FAIL, 0} |
231 | end if | |
232 | ||
233 | 71 | mantissa = sign * mantissa |
234 | ||
235 | 71 | if ch = 'e' or ch = 'E' then |
236 | -- get exponent sign | |
237 | 4 | e_sign = +1 |
238 | 4 | e_mag = 0 |
239 | 4 | get_ch() |
240 | 4 | if ch = '-' then |
241 | 1 | e_sign = -1 |
242 | 1 | get_ch() |
243 | 3 | elsif ch = '+' then |
244 | 1 | get_ch() |
245 | end if | |
246 | -- get exponent magnitude | |
247 | 4 | if ch >= '0' and ch <= '9' then |
248 | 3 | e_mag = ch - '0' |
249 | 3 | get_ch() |
250 | 3 | while ch >= '0' and ch <= '9' do |
251 | 2 | e_mag = e_mag * 10 + ch - '0' |
252 | 2 | get_ch() |
253 | 2 | end while |
254 | else | |
255 | 1 | return {GET_FAIL, 0} -- no exponent |
256 | end if | |
257 | 3 | e_mag *= e_sign |
258 | 3 | if e_mag > 308 then |
259 | -- rare case: avoid power() overflow | |
260 | 0 | mantissa *= power(10, 308) |
261 | 0 | if e_mag > 1000 then |
262 | 0 | e_mag = 1000 |
263 | end if | |
264 | 0 | for i = 1 to e_mag - 308 do |
265 | 0 | mantissa *= 10 |
266 | 0 | end for |
267 | else | |
268 | 3 | mantissa *= power(10, e_mag) |
269 | end if | |
270 | end if | |
271 | ||
272 | 70 | return {GET_SUCCESS, mantissa} |
273 | end function | |
274 | ||
275 | 99 | |
276 | -- read a Euphoria data object as a string of characters | |
277 | -- and return {error_flag, value} | |
278 | -- Note: ch is "live" at entry and exit of this routine | |
279 | sequence s, e | |
280 | integer e1 | |
281 | ||
282 | -- init | |
283 | 99 | while find(ch, white_space) do |
284 | 113 | get_ch() |
285 | 113 | end while |
286 | ||
287 | 99 | if ch = -1 then -- string is made of whitespace only |
288 | 2 | return {GET_EOF, 0} |
289 | end if | |
290 | ||
291 | 97 | while 1 do |
292 | 97 | if find(ch, START_NUMERIC) then |
293 | 35 | e = get_number() |
294 | 35 | if e[1] != GET_IGNORE then -- either a number or something illegal was read, so exit: the other goto |
295 | 35 | return e |
296 | end if -- else go read next item, starting at top of loop | |
297 | 0 | skip_blanks() |
298 | 0 | if ch=-1 or ch='}' then -- '}' is expected only in the "{--\n}" case |
299 | 0 | return {GET_NOTHING, 0} -- just a comment |
300 | end if | |
301 | ||
302 | 62 | elsif ch = '{' then |
303 | -- process a sequence | |
304 | 13 | s = {} |
305 | 13 | get_ch() |
306 | 13 | skip_blanks() |
307 | 13 | if ch = '}' then -- empty sequence |
308 | 0 | get_ch() |
309 | 0 | return {GET_SUCCESS, s} -- empty sequence |
310 | end if | |
311 | ||
312 | 13 | while TRUE do -- read: comment(s), element, comment(s), comma and so on till it terminates or errors out |
313 | 49 | while 1 do -- read zero or more comments and an element |
314 | 49 | e = Get() -- read next element, using standard function |
315 | 49 | e1 = e[1] |
316 | 49 | if e1 = GET_SUCCESS then |
317 | 49 | s = append(s, e[2]) |
318 | 49 | exit -- element read and added to result |
319 | 0 | elsif e1 != GET_IGNORE then |
320 | 0 | return e |
321 | -- else it was a comment, keep going | |
322 | 0 | elsif ch='}' then |
323 | 0 | get_ch() |
324 | 0 | return {GET_SUCCESS, s} -- empty sequence |
325 | end if | |
326 | 0 | end while |
327 | ||
328 | 49 | while 1 do -- now read zero or more post element comments |
329 | 49 | skip_blanks() |
330 | 49 | if ch = '}' then |
331 | 13 | get_ch() |
332 | 13 | return {GET_SUCCESS, s} |
333 | 36 | elsif ch!='-' then |
334 | 36 | exit |
335 | else -- comment starts after item and before comma | |
336 | 0 | e = get_number() -- reads anything starting with '-' |
337 | 0 | if e[1] != GET_IGNORE then -- it wasn't a comment, this is illegal |
338 | 0 | return {GET_FAIL, 0} |
339 | end if | |
340 | -- read next comment or , or } | |
341 | end if | |
342 | 0 | end while |
343 | 36 | if ch != ',' then |
344 | 0 | return {GET_FAIL, 0} |
345 | end if | |
346 | 36 | get_ch() -- skip comma |
347 | 36 | end while |
348 | ||
349 | 49 | elsif ch = '\"' then |
350 | 46 | return get_string() |
351 | 3 | elsif ch = '\'' then |
352 | 0 | return get_qchar() |
353 | else | |
354 | 3 | return {GET_FAIL, 0} |
355 | ||
356 | end if | |
357 | ||
358 | 0 | end while |
359 | ||
360 | end function | |
361 | ||
362 | integer leading_whitespace | |
363 | ||
364 | 73 | |
365 | -- read a Euphoria data object as a string of characters | |
366 | -- and return {error_flag, value, total number of characters, leading whitespace} | |
367 | -- Note: ch is "live" at entry and exit of this routine. | |
368 | -- Uses the regular Get() to read sequence elements. | |
369 | sequence s, e | |
370 | integer e1 | |
371 | natural offset | |
372 | ||
373 | -- init | |
374 | 73 | offset = string_next-1 |
375 | 73 | get_ch() |
376 | 73 | while find(ch, white_space) do |
377 | 1 | get_ch() |
378 | 1 | end while |
379 | ||
380 | 73 | if ch = -1 then -- string is made of whitespace only |
381 | 0 | return {GET_EOF, 0, string_next-1-offset ,string_next-1} |
382 | end if | |
383 | ||
384 | 73 | leading_whitespace = string_next-2-offset -- index of the last whitespace: string_next points past the first non whitespace |
385 | ||
386 | 73 | while 1 do |
387 | 73 | if find(ch, START_NUMERIC) then |
388 | 44 | e = get_number() |
389 | 44 | if e[1] != GET_IGNORE then -- either a number or something illegal was read, so exit: the other goto |
390 | 44 | return e & {string_next-1-offset-(ch!=-1), leading_whitespace} |
391 | end if -- else go read next item, starting at top of loop | |
392 | 0 | get_ch() |
393 | 0 | if ch=-1 then |
394 | 0 | return {GET_NOTHING, 0, string_next-1-offset-(ch!=-1), leading_whitespace} -- empty sequence |
395 | end if | |
396 | ||
397 | 29 | elsif ch = '{' then |
398 | -- process a sequence | |
399 | 3 | s = {} |
400 | 3 | get_ch() |
401 | 3 | skip_blanks() |
402 | 3 | if ch = '}' then -- empty sequence |
403 | 0 | get_ch() |
404 | 0 | return {GET_SUCCESS, s, string_next-1-offset-(ch!=-1), leading_whitespace} -- empty sequence |
405 | end if | |
406 | ||
407 | 3 | while TRUE do -- read: comment(s), element, comment(s), comma and so on till it terminates or errors out |
408 | 7 | while 1 do -- read zero or more comments and an element |
409 | 7 | e = Get() -- read next element, using standard function |
410 | 7 | e1 = e[1] |
411 | 7 | if e1 = GET_SUCCESS then |
412 | 7 | s = append(s, e[2]) |
413 | 7 | exit -- element read and added to result |
414 | 0 | elsif e1 != GET_IGNORE then |
415 | 0 | return e & {string_next-1-offset-(ch!=-1), leading_whitespace} |
416 | -- else it was a comment, keep going | |
417 | 0 | elsif ch='}' then |
418 | 0 | get_ch() |
419 | 0 | return {GET_SUCCESS, s, string_next-1-offset-(ch!=-1),leading_whitespace} -- empty sequence |
420 | end if | |
421 | 0 | end while |
422 | ||
423 | 7 | while 1 do -- now read zero or more post element comments |
424 | 7 | skip_blanks() |
425 | 7 | if ch = '}' then |
426 | 3 | get_ch() |
427 | 3 | return {GET_SUCCESS, s, string_next-1-offset-(ch!=-1), leading_whitespace} |
428 | 4 | elsif ch!='-' then |
429 | 4 | exit |
430 | else -- comment starts after item and before comma | |
431 | 0 | e = get_number() -- reads anything starting with '-' |
432 | 0 | if e[1] != GET_IGNORE then -- it was not a comment, this is illegal |
433 | 0 | return {GET_FAIL, 0, string_next-1-offset-(ch!=-1),leading_whitespace} |
434 | end if | |
435 | -- read next comment or , or } | |
436 | end if | |
437 | 0 | end while |
438 | 4 | if ch != ',' then |
439 | 0 | return {GET_FAIL, 0, string_next-1-offset-(ch!=-1), leading_whitespace} |
440 | end if | |
441 | 4 | get_ch() -- skip comma |
442 | 4 | end while |
443 | ||
444 | 26 | elsif ch = '\"' then |
445 | 21 | e = get_string() |
446 | 21 | return e & {string_next-1-offset-(ch!=-1), leading_whitespace} |
447 | 5 | elsif ch = '\'' then |
448 | 0 | e = get_qchar() |
449 | 0 | return e & {string_next-1-offset-(ch!=-1), leading_whitespace} |
450 | else | |
451 | 5 | return {GET_FAIL, 0, string_next-1-offset-(ch!=-1), leading_whitespace} |
452 | ||
453 | end if | |
454 | ||
455 | 0 | end while |
456 | ||
457 | end function | |
458 | ||
459 | --**** | |
460 | -- === Answer Types | |
461 | ||
462 | public constant | |
463 | 101 | GET_SHORT_ANSWER = routine_id("Get"), |
464 | 101 | GET_LONG_ANSWER = routine_id("Get2") |
465 | ||
466 | 116 | |
467 | 116 | if answer_type != GET_SHORT_ANSWER and answer_type != GET_LONG_ANSWER then |
468 | 0 | crash("Invalid type of answer, please only use %s (the default) or %s.", {"GET_SHORT_ANSWER", "GET_LONG_ANSWER"}) |
469 | end if | |
470 | 116 | if atom(target) then -- get() |
471 | 13 | input_file = target |
472 | 13 | if start_point then |
473 | 0 | if seek(target, where(target)+start_point) then |
474 | 0 | crash("Initial seek() for get() failed!") |
475 | end if | |
476 | end if | |
477 | 13 | string_next = 1 |
478 | 13 | input_string = 0 |
479 | else | |
480 | 103 | input_string = target |
481 | 103 | string_next = start_point |
482 | end if | |
483 | 116 | if answer_type = GET_SHORT_ANSWER then |
484 | 43 | get_ch() |
485 | end if | |
486 | 116 | return call_func(answer_type, {}) |
487 | end function | |
488 | ||
489 | --**** | |
490 | -- === Routines | |
491 | -- | |
492 | ||
493 | --** | |
494 | -- Input, from an open file, a human-readable string of characters representing a Euphoria object. | |
495 | -- Convert the string into the numeric value of that object. | |
496 | -- | |
497 | -- Parameters: | |
498 | -- # ##file## : an integer, the handle to an open file from which to read | |
499 | -- # ##offset## : an integer, an offset to apply to file position before reading. Defaults to 0. | |
500 | -- # ##answer## : an integer, either ##GET_SHORT_ANSWER## (the default) or ##GET_LONG_ANSWER##. | |
501 | -- | |
502 | -- Returns: | |
503 | -- A **sequence**, of length 2 (##GET_SHORT_ANSWER##) or 4 (##GET_LONG_ANSWER##), made of | |
504 | -- | |
505 | -- * an integer, the return status. This is any of: | |
506 | -- ** ##GET_SUCCESS## ~-- object was read successfully | |
507 | -- ** ##GET_EOF## ~-- end of file before object was read completely | |
508 | -- ** ##GET_FAIL## ~-- object is not syntactically correct | |
509 | -- ** ##GET_NOTHING## ~-- nothing was read, even a partial object string, before end of input | |
510 | -- * an object, the value that was read. This is valid only if return status is ##GET_SUCCESS##. | |
511 | -- * an integer, the number of characters read. On an error, this is the point at which the | |
512 | -- error was detected. | |
513 | -- * an integer, the amount of initial whitespace read before the first active character was found | |
514 | -- | |
515 | -- Comments: | |
516 | -- When ##answer## is not specified, or explicitly ##GET_SHORT_ANSWER##, only the first two | |
517 | -- elements in the returned sequence are actually returned. | |
518 | -- | |
519 | -- The ##GET_NOTHING## return status will not be returned if ##answer## is ##GET_SHORT_ANSWER##. | |
520 | -- | |
521 | -- ##get()## can read arbitrarily complicated Euphoria objects. You | |
522 | -- could have a long sequence of values in braces and separated by | |
523 | -- commas and comments, e.g. ##{23, {49, 57}, 0.5, -1, 99, 'A', "john"}##. | |
524 | -- A single call to get() will read in this entire sequence and return its value as a result, | |
525 | -- as well as complementary information. | |
526 | -- | |
527 | -- If a nonzero offset is supplied, it is interpreted as an offset to the current file | |
528 | -- position, and the file will be seek()ed there first. | |
529 | -- | |
530 | -- ##get()## returns a 2 or 4 element sequence, like ##[[:value]]()## does: | |
531 | -- | |
532 | -- * a status code (success/error/end of file/no value at all) | |
533 | -- * the value just read (meaningful only when the status code is ##GET_SUCCESS##) | |
534 | -- (optionally) | |
535 | -- * the total number of characters read | |
536 | -- * the amount of initial whitespace read. | |
537 | -- | |
538 | -- Using the default value for answer, or setting it to ##GET_SHORT_ANSWER##, returns 2 elements. | |
539 | -- Setting it to ##GET_LONG_ANSWER## causes 4 elements to be returned. | |
540 | -- | |
541 | -- Each call to ##get()## picks up where the previous call left off. For instance, a series of 5 | |
542 | -- calls to ##get()## would be needed to read in | |
543 | -- | |
544 | -- {{{ | |
545 | -- "99 5.2 {1, 2, 3} "Hello" -1" | |
546 | -- }}} | |
547 | -- | |
548 | -- On the sixth and any subsequent call to ##get()## you would see a ##GET_EOF## status. If you had | |
549 | -- something like | |
550 | -- | |
551 | -- {{{ | |
552 | -- {1, 2, xxx} | |
553 | -- }}} | |
554 | -- | |
555 | -- in the input stream you would see a ##GET_FAIL## error status because xxx is not a Euphoria | |
556 | -- object. And seeing | |
557 | -- | |
558 | -- {{{ | |
559 | -- -- something\nBut no value | |
560 | -- }}} | |
561 | -- | |
562 | -- and the input stream stops right there, you'll receive a status code of ##GET_NOTHING##, | |
563 | -- because nothing but whitespace or comments was read. If you had opted for a short answer, | |
564 | -- you'd get ##GET_EOF## instead. | |
565 | -- | |
566 | -- Multiple "top-level" objects in the input stream must be | |
567 | -- separated from each other with one or more "whitespace" | |
568 | -- characters (blank, tab, \r or \n). At the very least, a top | |
569 | -- level number must be followed by a white space from the following object. | |
570 | -- Whitespace is not necessary //within// a top-level object. Comments, terminated by either | |
571 | -- '\n' or '\r', are allowed anywhere inside sequences, and ignored if at the top level. | |
572 | -- A call to ##get()## will read one entire top-level object, plus possibly one additional | |
573 | -- (whitespace) character, after a top level number, even though the next object may have an | |
574 | -- identifiable starting point. | |
575 | -- | |
576 | -- The combination of ##[[:print]]()## and ##get()## can be used to save a | |
577 | -- Euphoria object to disk and later read it back. This technique | |
578 | -- could be used to implement a database as one or more large | |
579 | -- Euphoria sequences stored in disk files. The sequences could be | |
580 | -- read into memory, updated and then written back to disk after | |
581 | -- each series of transactions is complete. Remember to write out | |
582 | -- a whitespace character (using ##[[:puts]]()##) after each call to ##[[:print]]()##, | |
583 | -- at least when a top level number was just printed. | |
584 | -- | |
585 | -- The value returned is not meaningful unless you have a ##GET_SUCCESS## status. | |
586 | -- | |
587 | -- Example 1: | |
588 | -- | |
589 | -- -- If he types 77.5, get(0) would return: | |
590 | -- {GET_SUCCESS, 77.5} | |
591 | -- | |
592 | -- -- whereas gets(0) would return: | |
593 | -- "77.5\n" | |
594 | -- | |
595 | -- | |
596 | -- Example 2: | |
597 | -- See ##bin\mydata.ex## | |
598 | -- | |
599 | -- See Also: | |
600 | -- [[:value]] | |
601 | ||
602 | 13 | |
603 | -- Read the string representation of a Euphoria object | |
604 | -- from a file. Convert to the value of the object. | |
605 | -- Return {error_status, value}. | |
606 | -- Embedded comments inside sequences are now supported. | |
607 | 13 | return get_value(file, offset, answer) |
608 | end function | |
609 | ||
610 | --** | |
611 | -- Read, from a string, a human-readable string of characters representing a Euphoria object. | |
612 | -- Convert the string into the numeric value of that object. | |
613 | -- | |
614 | -- Parameters: | |
615 | -- # ##st## : a sequence, from which to read text | |
616 | -- # ##offset## : an integer, the position at which to start reading. Defaults to 1. | |
617 | -- # ##answer## : an integer, either GET_SHORT_ANSWER (the default) or GET_LONG_ANSWER. | |
618 | -- | |
619 | -- Returns: | |
620 | -- A **sequence**, of length 2 (GET_SHORT_ANSWER) or 4 (GET_LONG_ANSWER), made of | |
621 | -- | |
622 | -- * an integer, the return status. This is any of | |
623 | -- ** ##GET_SUCCESS## ~-- object was read successfully | |
624 | -- ** ##GET_EOF## ~-- end of file before object was read completely | |
625 | -- ** ##GET_FAIL## ~-- object is not syntactically correct | |
626 | -- ** ##GET_NOTHING## ~-- nothing was read, even a partial object string, before end of input | |
627 | -- * an object, the value that was read. This is valid only if return status is ##GET_SUCCESS##. | |
628 | -- * an integer, the number of characters read. On an error, this is the point at which the | |
629 | -- error was detected. | |
630 | -- * an integer, the amount of initial whitespace read before the first active character was found | |
631 | -- | |
632 | -- Comments: | |
633 | -- When ##answer## is not specified, or explicitly ##GET_SHORT_ANSWER##, only the first two | |
634 | -- elements in the returned sequence are actually returned. | |
635 | -- | |
636 | -- This works the same as [[:get]](), but it reads from a string that you supply, rather than | |
637 | -- from a file or device. | |
638 | -- | |
639 | -- After reading one valid representation of a Euphoria object, ##value()## will stop reading | |
640 | -- and ignore any additional characters in the string. For example, "36" and "36P" will | |
641 | -- both give you ##{GET_SUCCESS, 36}##. | |
642 | -- | |
643 | -- The function returns ##{return_status, value}## if the answer type is not passed or set to | |
644 | -- ##GET_SHORT_ANSWER##. If set to ##GET_LONG_ANSWER##, the number of characters read and the | |
645 | -- amount of leading whitespace are returned in 3rd and 4th position. The ##GET_NOTHING## return | |
646 | -- status can occur only on a long answer. | |
647 | -- | |
648 | -- Example 1: | |
649 | -- | |
650 | -- s = value("12345"} | |
651 | -- s is {GET_SUCCESS, 12345} | |
652 | -- | |
653 | -- | |
654 | -- Example 2: | |
655 | -- | |
656 | -- s = value("{0, 1, -99.9}") | |
657 | -- -- s is {GET_SUCCESS, {0, 1, -99.9}} | |
658 | -- | |
659 | -- | |
660 | -- Example 3: | |
661 | -- | |
662 | -- s = value("+++") | |
663 | -- -- s is {GET_FAIL, 0} | |
664 | -- | |
665 | -- | |
666 | -- See Also: | |
667 | -- [[:get]] | |
668 | ||
669 | 95 | |
670 | -- Read the representation of a Euphoria object | |
671 | -- from a sequence of characters. Convert to the value of the object. | |
672 | -- Trailing whitespace or comments are not considered. | |
673 | -- Return {error_status, value}. | |
674 | -- Embedded comments inside sequence are now supported. | |
675 | 95 | return get_value(st, start_point, answer) |
676 | end function | |
677 | ||
678 | --** | |
679 | -- Perform a value() operation on a sequence, returning the value on success or | |
680 | -- the default on failure. | |
681 | -- | |
682 | -- Parameters: | |
683 | -- # ##st## : object to retrieve value from. | |
684 | -- # ##def## : the value returned if ##st## is an atom or ##value(st)## fails. | |
685 | -- # ##start_point## : an integer, the position in ##st## at which to start | |
686 | -- getting the value from. Defaults to 1 | |
687 | -- | |
688 | -- Returns: | |
689 | -- * If ##st##, is an atom then ##def## is returned. | |
690 | -- * If ##value(st)##, call is a success, then ##value()[2]##, otherwise it will return | |
691 | -- the parameter #def#. | |
692 | -- | |
693 | -- Examples: | |
694 | -- | |
695 | -- object i = defaulted_value("10", 0) | |
696 | -- -- i is 10 | |
697 | -- | |
698 | -- i = defaulted_value("abc", 39) | |
699 | -- -- i is 39 | |
700 | -- | |
701 | -- i = defaulted_value(12, 42) | |
702 | -- -- i is 42 | |
703 | -- | |
704 | -- i = defaulted_value("{1,2}", 42) | |
705 | -- -- i is {1,2} | |
706 | -- | |
707 | -- | |
708 | -- See Also: | |
709 | -- [[:value]] | |
710 | -- | |
711 | ||
712 | 9 | |
713 | 9 | if atom(st) then |
714 | 1 | return def |
715 | end if | |
716 | ||
717 | 8 | object result = get_value(st,start_point, GET_SHORT_ANSWER) |
718 | ||
719 | 8 | if result[1] = GET_SUCCESS then |
720 | 6 | return result[2] |
721 | end if | |
722 | ||
723 | 2 | return def |
724 | end function |