Some changes based on feedback.
[pforth] / fth / file.fth
... / ...
CommitLineData
1\ READ-LINE and WRITE-LINE
2\
3\ This code is part of pForth.
4\
5\ The pForth software code is dedicated to the public domain,
6\ and any third party may reproduce, distribute and modify
7\ the pForth software code or any derivative works thereof
8\ without any compensation or license. The pForth software
9\ code is provided on an "as is" basis without any warranty
10\ of any kind, including, without limitation, the implied
11\ warranties of merchantability and fitness for a particular
12\ purpose and their equivalents under the laws of any jurisdiction.
13
14private{
15
1610 constant \N
1713 constant \R
18
19\ Unread one char from file FILEID.
20: UNREAD { fileid -- ior }
21 fileid file-position ( ud ior )
22 ?dup
23 IF nip nip \ IO error
24 ELSE 1 s>d d- fileid reposition-file
25 THEN
26;
27
28\ Read the next available char from file FILEID and if it is a \n then
29\ skip it; otherwise unread it. IOR is non-zero if an error occured.
30\ C-ADDR is a buffer that can hold at least one char.
31: SKIP-\N { c-addr fileid -- ior }
32 c-addr 1 fileid read-file ( u ior )
33 ?dup
34 IF \ Read error?
35 nip
36 ELSE ( u )
37 0=
38 IF \ End of file?
39 0
40 ELSE
41 c-addr c@ \n = ( is-it-a-\n? )
42 IF 0
43 ELSE fileid unread
44 THEN
45 THEN
46 THEN
47;
48
49\ This is just s\" \n" but s\" isn't yet available.
50create (LINE-TERMINATOR) \n c,
51: LINE-TERMINATOR ( -- c-addr u ) (line-terminator) 1 ;
52
53}private
54
55\ This treats \n, \r\n, and \r as line terminator. Reading is done
56\ one char at a time with READ-FILE hence READ-FILE should probably do
57\ some form of buffering for good efficiency.
58: READ-LINE ( c-addr u1 fileid -- u2 flag ior )
59 { a u f }
60 u 0 ?DO
61 a i chars + 1 f read-file ( u ior' )
62 ?dup IF nip i false rot UNLOOP EXIT THEN \ Read error? ( u )
63 0= IF i i 0<> 0 UNLOOP EXIT THEN \ End of file? ( )
64 a i chars + c@
65 CASE
66 \n OF i true 0 UNLOOP EXIT ENDOF
67 \r OF
68 \ Detect \r\n
69 a i chars + f skip-\n ( ior )
70 ?dup IF i false rot UNLOOP EXIT THEN \ IO Error? ( )
71 i true 0 UNLOOP EXIT
72 ENDOF
73 ENDCASE
74 LOOP
75 \ Line doesn't fit in buffer
76 u true 0
77;
78
79: WRITE-LINE ( c-addr u fileid -- ior )
80 { f }
81 f write-file ( ior )
82 ?dup
83 IF \ IO error
84 ELSE line-terminator f write-file
85 THEN
86;
87
88privatize