1
1
import os. libc ;
2
2
3
- type stdio_reader = state obj {
4
- fn getc( ) -> int;
5
- fn ungetc ( int i) ;
6
- } ;
7
-
8
- fn new_stdio_reader ( str path ) -> stdio_reader {
9
- state obj stdio_FILE_reader ( os. libc . FILE f) {
10
- fn getc ( ) -> int {
11
- ret os. libc . fgetc ( f) ;
12
- }
13
- fn ungetc ( int i) {
14
- os. libc . ungetc ( i, f) ;
15
- }
16
- drop {
17
- os. libc . fclose ( f) ;
18
- }
19
- }
20
- auto FILE = os. libc . fopen ( _str. buf ( path) , _str. buf ( "r" ) ) ;
21
- check ( FILE as uint != 0 u) ;
22
- ret stdio_FILE_reader ( FILE ) ;
3
+ native "rust" mod rustrt {
4
+ fn rust_get_stdin ( ) -> os. libc. FILE ;
5
+ fn rust_get_stdout ( ) -> os. libc. FILE ;
23
6
}
24
7
8
+ // Reading
25
9
26
- type buf_reader = state obj {
27
- fn read( ) -> vec[ u8] ;
28
- } ;
29
-
30
- type buf_writer = state obj {
31
- fn write( vec[ u8] v) ;
32
- } ;
33
-
34
- fn default_bufsz ( ) -> uint {
35
- ret 4096 u;
36
- }
37
-
38
- fn new_buf ( ) -> vec[ u8 ] {
39
- ret _vec. alloc [ u8] ( default_bufsz ( ) ) ;
40
- }
41
-
42
- fn new_buf_reader ( str path ) -> buf_reader {
10
+ // TODO This is all buffered. We might need an unbuffered variant as well
43
11
44
- state obj fd_buf_reader ( int fd , mutable vec [ u8 ] buf ) {
12
+ tag seek_style { seek_set ; seek_end ; seek_cur ; }
45
13
46
- fn read ( ) -> vec[ u8 ] {
47
-
48
- // Ensure our buf is singly-referenced.
49
- if ( _vec. rustrt . refcount [ u8] ( buf) != 1 u) {
50
- buf = new_buf ( ) ;
51
- }
52
-
53
- auto len = default_bufsz ( ) ;
54
- auto vbuf = _vec. buf [ u8] ( buf) ;
55
- auto count = os. libc . read ( fd, vbuf, len) ;
56
-
57
- if ( count < 0 ) {
58
- log "error filling buffer" ;
59
- log sys. rustrt . last_os_error ( ) ;
60
- fail;
61
- }
14
+ type reader =
15
+ state obj {
16
+ impure fn read_byte( ) -> u8;
17
+ impure fn read_bytes ( uint len) -> vec[ u8 ] ;
18
+ impure fn read_char ( ) -> int ;
19
+ impure fn unread_char ( int i) ;
20
+ impure fn read_c_str ( ) -> str ;
21
+ impure fn read_le_uint ( uint size) -> uint ;
22
+ impure fn read_le_int ( uint size) -> int ;
23
+
24
+ impure fn seek ( int offset , seek_style whence) ;
25
+ } ;
62
26
63
- _vec. len_set [ u8] ( buf, count as uint ) ;
64
- ret buf;
27
+ state obj FILE_reader ( os. libc . FILE f, bool must_close) {
28
+ impure fn read_byte ( ) -> u8 {
29
+ ret os. libc . fgetc ( f) as u8 ;
30
+ }
31
+ impure fn read_bytes ( uint len) -> vec[ u8 ] {
32
+ auto buf = _vec. alloc [ u8] ( len) ;
33
+ auto read = os. libc . fread ( _vec. buf [ u8] ( buf) , 1 u, len, f) ;
34
+ check ( read == len) ;
35
+ ret buf;
36
+ }
37
+ impure fn read_char ( ) -> int {
38
+ ret os. libc . fgetc ( f) ;
39
+ }
40
+ impure fn unread_char ( int ch) {
41
+ os. libc . ungetc ( ch, f) ;
42
+ }
43
+ impure fn read_c_str ( ) -> str {
44
+ auto buf = "" ;
45
+ while ( true ) {
46
+ auto ch = os. libc . fgetc ( f) ;
47
+ if ( ch < 1 ) { break ; }
48
+ buf += _str. unsafe_from_bytes ( vec ( ch as u8 ) ) ;
65
49
}
66
-
67
- drop {
68
- os. libc . close ( fd) ;
50
+ ret buf;
51
+ }
52
+ // TODO deal with eof?
53
+ impure fn read_le_uint ( uint size) -> uint {
54
+ auto val = 0 u;
55
+ auto pos = 0 u;
56
+ while ( size > 0 u) {
57
+ val += ( os. libc . fgetc ( f) as uint ) << pos;
58
+ pos += 8 u;
59
+ size -= 1 u;
60
+ }
61
+ ret val;
62
+ }
63
+ impure fn read_le_int ( uint size) -> int {
64
+ auto val = 0 u;
65
+ auto pos = 0 u;
66
+ while ( size > 0 u) {
67
+ val += ( os. libc . fgetc ( f) as uint ) << pos;
68
+ pos += 8 u;
69
+ size -= 1 u;
69
70
}
71
+ ret val as int ; // TODO does that work?
72
+ }
73
+ impure fn seek ( int offset , seek_style whence) {
74
+ auto wh;
75
+ alt ( whence) {
76
+ case ( seek_set) { wh = 0 ; }
77
+ case ( seek_cur) { wh = 1 ; }
78
+ case ( seek_end) { wh = 2 ; }
79
+ }
80
+ check ( os. libc . fseek ( f, offset, wh) == 0 ) ;
81
+ }
82
+ drop {
83
+ if ( must_close) { os. libc . fclose ( f) ; }
70
84
}
85
+ }
71
86
72
- auto fd = os. libc . open ( _str. buf ( path) ,
73
- os. libc_constants . O_RDONLY ( ) |
74
- os. libc_constants . O_BINARY ( ) ,
75
- 0 u) ;
87
+ fn stdin( ) -> reader {
88
+ ret FILE_reader ( rustrt. rust_get_stdin ( ) , false) ;
89
+ }
76
90
77
- if ( fd < 0 ) {
78
- log "error opening file for reading" ;
79
- log sys. rustrt . last_os_error ( ) ;
80
- fail;
81
- }
82
- ret fd_buf_reader ( fd, new_buf ( ) ) ;
91
+ fn file_reader ( str path ) -> reader {
92
+ auto f = os. libc . fopen ( _str. buf ( path) , _str. buf ( "r" ) ) ;
93
+ check ( f as uint != 0 u) ;
94
+ ret FILE_reader ( f, true ) ;
83
95
}
84
96
97
+ // Writing
98
+
99
+ // TODO This is all unbuffered. We might need a buffered variant as well
100
+
85
101
tag fileflag {
86
102
append;
87
103
create;
88
104
truncate;
89
105
none;
90
106
}
91
107
108
+ type buf_writer = state obj {
109
+ fn write( vec[ u8] v) ;
110
+ } ;
111
+
92
112
state obj fd_buf_writer ( int fd, bool must_close) {
93
113
fn write ( vec[ u8] v ) {
94
114
auto len = _vec. len [ u8] ( v) ;
@@ -143,8 +163,21 @@ type writer =
143
163
impure fn write_str( str s) ;
144
164
impure fn write_int ( int n) ;
145
165
impure fn write_uint ( uint n) ;
166
+ impure fn write_bytes ( vec[ u8] bytes) ;
167
+ impure fn write_le_uint ( uint n, uint size) ;
168
+ impure fn write_le_int ( int n, uint size) ;
146
169
} ;
147
170
171
+ fn uint_to_le_bytes( uint n, uint size) -> vec[ u8 ] {
172
+ let vec[ u8] bytes = vec ( ) ;
173
+ while ( size > 0 u) {
174
+ bytes += vec ( ( n & 255 u) as u8 ) ;
175
+ n >>= 8 u;
176
+ size -= 1 u;
177
+ }
178
+ ret bytes;
179
+ }
180
+
148
181
state obj new_writer ( buf_writer out) {
149
182
impure fn write_str ( str s) {
150
183
out. write ( _str. bytes ( s) ) ;
@@ -155,14 +188,23 @@ state obj new_writer(buf_writer out) {
155
188
impure fn write_uint ( uint n) {
156
189
out. write ( _str. bytes ( _uint. to_str ( n, 10 u) ) ) ;
157
190
}
191
+ impure fn write_bytes ( vec[ u8] bytes) {
192
+ out. write ( bytes) ;
193
+ }
194
+ impure fn write_le_uint ( uint n, uint size) {
195
+ out. write ( uint_to_le_bytes ( n, size) ) ;
196
+ }
197
+ impure fn write_le_int ( int n, uint size) {
198
+ out. write ( uint_to_le_bytes ( n as uint , size) ) ;
199
+ }
158
200
}
159
201
160
202
fn file_writer ( str path , vec[ fileflag] flags ) -> writer {
161
203
ret new_writer ( file_buf_writer ( path, flags) ) ;
162
204
}
163
205
164
- // FIXME it would be great if this could be a const named stdout
165
- fn stdout_writer ( ) -> writer {
206
+ // FIXME it would be great if this could be a const
207
+ fn stdout ( ) -> writer {
166
208
ret new_writer ( fd_buf_writer ( 1 , false ) ) ;
167
209
}
168
210
@@ -172,21 +214,21 @@ type str_writer =
172
214
fn get_str ( ) -> str ;
173
215
} ;
174
216
175
- type str_buf = @rec( mutable str buf) ;
217
+ type byte_buf = @rec( mutable vec[ u8 ] buf) ;
218
+
219
+ state obj byte_buf_writer( byte_buf buf) {
220
+ fn write( vec[ u8 ] v) { buf. buf += v; }
221
+ }
176
222
177
223
// TODO awkward! it's not possible to implement a writer with an extra method
178
224
fn string_writer( ) -> str_writer {
179
- auto buf = @rec( mutable buf = "") ;
180
- state obj str_writer_writer( str_buf buf) {
181
- impure fn write_str( str s) { buf. buf += s; }
182
- impure fn write_int( int n) { buf. buf += _int. to_str ( n, 10 u) ; }
183
- impure fn write_uint ( uint n) { buf. buf += _uint. to_str ( n, 10 u) ; }
184
- }
185
- state obj str_writer_wrap ( writer wr, str_buf buf) {
225
+ let vec[ u8 ] b = vec( ) ;
226
+ let byte_buf buf = @rec( mutable buf = b) ;
227
+ state obj str_writer_wrap( writer wr, byte_buf buf) {
186
228
fn get_writer ( ) -> writer { ret wr; }
187
- fn get_str ( ) -> str { ret buf. buf ; }
229
+ fn get_str ( ) -> str { ret _str . unsafe_from_bytes ( buf. buf ) ; }
188
230
}
189
- ret str_writer_wrap ( str_writer_writer ( buf) , buf) ;
231
+ ret str_writer_wrap ( new_writer ( byte_buf_writer ( buf) ) , buf) ;
190
232
}
191
233
192
234
//
0 commit comments