Skip to content

Commit 441697a

Browse files
marijnhgraydon
authored andcommitted
Extend stream functionality
Writer and reader streams now come with methods to write and read little-endian numbers. Whether that is the right place for such methods is debatable, but for now, that's where they live.
1 parent c731d62 commit 441697a

File tree

8 files changed

+140
-89
lines changed

8 files changed

+140
-89
lines changed

src/comp/driver/rustc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impure fn pretty_print_input(session.session sess,
6868
auto def = tup(0, 0);
6969
auto p = front.parser.new_parser(sess, env, def, input);
7070
auto crate = front.parser.parse_crate_from_source_file(p);
71-
pretty.pprust.print_ast(crate.node.module, std.io.stdout_writer());
71+
pretty.pprust.print_ast(crate.node.module, std.io.stdout());
7272
}
7373

7474
fn warn_wrong_compiler() {

src/comp/front/lexer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import std.io.stdio_reader;
1+
import std.io;
22
import std._str;
33
import std.map;
44
import std.map.hashmap;
@@ -18,9 +18,9 @@ state type reader = state obj {
1818
fn get_reserved() -> hashmap[str,()];
1919
};
2020

21-
fn new_reader(stdio_reader rdr, str filename) -> reader
21+
impure fn new_reader(io.reader rdr, str filename) -> reader
2222
{
23-
state obj reader(stdio_reader rdr,
23+
state obj reader(io.reader rdr,
2424
str filename,
2525
mutable char c,
2626
mutable char n,
@@ -72,7 +72,7 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
7272
col += 1u;
7373
}
7474

75-
n = rdr.getc() as char;
75+
n = rdr.read_char() as char;
7676
}
7777

7878
fn mark() {
@@ -200,8 +200,8 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
200200
reserved.insert("m128", ()); // IEEE 754-2008 'decimal128'
201201
reserved.insert("dec", ()); // One of m32, m64, m128
202202

203-
ret reader(rdr, filename, rdr.getc() as char, rdr.getc() as char,
204-
1u, 0u, 1u, 0u, keywords, reserved);
203+
ret reader(rdr, filename, rdr.read_char() as char,
204+
rdr.read_char() as char, 1u, 0u, 1u, 0u, keywords, reserved);
205205
}
206206

207207

src/comp/front/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impure fn new_parser(session.session sess,
115115
if (_str.ends_with(path, ".rc")) {
116116
ftype = CRATE_FILE;
117117
}
118-
auto srdr = io.new_stdio_reader(path);
118+
auto srdr = io.file_reader(path);
119119
auto rdr = lexer.new_reader(srdr, path);
120120
auto npos = rdr.get_curr_pos();
121121
ret stdio_parser(sess, env, ftype, lexer.next_token(rdr),

src/lib/io.rs

Lines changed: 123 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,114 @@
11
import os.libc;
22

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 != 0u);
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;
236
}
247

8+
// Reading
259

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 4096u;
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
4311

44-
state obj fd_buf_reader(int fd, mutable vec[u8] buf) {
12+
tag seek_style {seek_set; seek_end; seek_cur;}
4513

46-
fn read() -> vec[u8] {
47-
48-
// Ensure our buf is singly-referenced.
49-
if (_vec.rustrt.refcount[u8](buf) != 1u) {
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+
};
6226

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), 1u, 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));
6549
}
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 = 0u;
55+
auto pos = 0u;
56+
while (size > 0u) {
57+
val += (os.libc.fgetc(f) as uint) << pos;
58+
pos += 8u;
59+
size -= 1u;
60+
}
61+
ret val;
62+
}
63+
impure fn read_le_int(uint size) -> int {
64+
auto val = 0u;
65+
auto pos = 0u;
66+
while (size > 0u) {
67+
val += (os.libc.fgetc(f) as uint) << pos;
68+
pos += 8u;
69+
size -= 1u;
6970
}
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);}
7084
}
85+
}
7186

72-
auto fd = os.libc.open(_str.buf(path),
73-
os.libc_constants.O_RDONLY() |
74-
os.libc_constants.O_BINARY(),
75-
0u);
87+
fn stdin() -> reader {
88+
ret FILE_reader(rustrt.rust_get_stdin(), false);
89+
}
7690

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 != 0u);
94+
ret FILE_reader(f, true);
8395
}
8496

97+
// Writing
98+
99+
// TODO This is all unbuffered. We might need a buffered variant as well
100+
85101
tag fileflag {
86102
append;
87103
create;
88104
truncate;
89105
none;
90106
}
91107

108+
type buf_writer = state obj {
109+
fn write(vec[u8] v);
110+
};
111+
92112
state obj fd_buf_writer(int fd, bool must_close) {
93113
fn write(vec[u8] v) {
94114
auto len = _vec.len[u8](v);
@@ -143,8 +163,21 @@ type writer =
143163
impure fn write_str(str s);
144164
impure fn write_int(int n);
145165
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);
146169
};
147170

171+
fn uint_to_le_bytes(uint n, uint size) -> vec[u8] {
172+
let vec[u8] bytes = vec();
173+
while (size > 0u) {
174+
bytes += vec((n & 255u) as u8);
175+
n >>= 8u;
176+
size -= 1u;
177+
}
178+
ret bytes;
179+
}
180+
148181
state obj new_writer(buf_writer out) {
149182
impure fn write_str(str s) {
150183
out.write(_str.bytes(s));
@@ -155,14 +188,23 @@ state obj new_writer(buf_writer out) {
155188
impure fn write_uint(uint n) {
156189
out.write(_str.bytes(_uint.to_str(n, 10u)));
157190
}
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+
}
158200
}
159201

160202
fn file_writer(str path, vec[fileflag] flags) -> writer {
161203
ret new_writer(file_buf_writer(path, flags));
162204
}
163205

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 {
166208
ret new_writer(fd_buf_writer(1, false));
167209
}
168210

@@ -172,21 +214,21 @@ type str_writer =
172214
fn get_str() -> str;
173215
};
174216

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+
}
176222

177223
// TODO awkward! it's not possible to implement a writer with an extra method
178224
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, 10u); }
183-
impure fn write_uint(uint n) { buf.buf += _uint.to_str(n, 10u); }
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) {
186228
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);}
188230
}
189-
ret str_writer_wrap(str_writer_writer(buf), buf);
231+
ret str_writer_wrap(new_writer(byte_buf_writer(buf)), buf);
190232
}
191233

192234
//

src/lib/linux_os.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ native mod libc = "libc.so.6" {
1313
fn fclose(FILE f);
1414
fn fgetc(FILE f) -> int;
1515
fn ungetc(int c, FILE f);
16+
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
17+
fn fseek(FILE f, int offset, int whence) -> int;
1618

1719
type dir;
1820
fn opendir(sbuf d) -> dir;

src/lib/macos_os.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ native mod libc = "libc.dylib" {
1212
fn fclose(FILE f);
1313
fn fgetc(FILE f) -> int;
1414
fn ungetc(int c, FILE f);
15+
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
16+
fn fseek(FILE f, int offset, int whence) -> int;
1517

1618
type dir;
1719
fn opendir(sbuf d) -> dir;

src/lib/win32_os.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ native mod libc = "msvcrt.dll" {
1212
fn fclose(FILE f);
1313
fn fgetc(FILE f) -> int;
1414
fn ungetc(int c, FILE f);
15+
fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
16+
fn fseek(FILE f, int offset, int whence) -> int;
1517
}
1618

1719
mod libc_constants {

src/rt/rust_builtin.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ rust_file_is_dir(rust_task *task, rust_str *path) {
408408
return S_ISDIR(buf.st_mode);
409409
}
410410

411+
extern "C" CDECL FILE* rust_get_stdin() {return stdin;}
412+
extern "C" CDECL FILE* rust_get_stdout() {return stdout;}
413+
411414
//
412415
// Local Variables:
413416
// mode: C++

0 commit comments

Comments
 (0)