Skip to content

Commit f75a3a6

Browse files
committed
---
yaml --- r: 83819 b: refs/heads/try c: b509f79 h: refs/heads/master i: 83817: c0c9c9e 83815: e21ecc1 v: v3
1 parent 4807d5d commit f75a3a6

File tree

3 files changed

+241
-39
lines changed

3 files changed

+241
-39
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 0e4d1fc8cae42e15e00f71d9f439b01bb25a86ae
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 6c08cc2db4f98e9f07ae7d50338396c4123c2f0a
5-
refs/heads/try: 62812f1e38f438dfc666cd9d164b4377063f8794
5+
refs/heads/try: b509f7905a578663d57121973b4a9a6b619341c2
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c

branches/try/src/libextra/base64.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ impl<'self> ToBase64 for &'self [u8] {
6464
*
6565
* ```rust
6666
* extern mod extra;
67-
* use extra::base64::{ToBase64, STANDARD};
67+
* use extra::base64::{ToBase64, standard};
6868
*
6969
* fn main () {
70-
* let str = [52,32].to_base64(STANDARD);
71-
* println!("base 64 output: {}", str);
70+
* let str = [52,32].to_base64(standard);
71+
* println!("{}", str);
7272
* }
7373
* ```
7474
*/
@@ -172,19 +172,16 @@ impl<'self> FromBase64 for &'self str {
172172
*
173173
* ```rust
174174
* extern mod extra;
175-
* use extra::base64::{ToBase64, FromBase64, STANDARD};
175+
* use extra::base64::{ToBase64, FromBase64, standard};
176176
* use std::str;
177177
*
178178
* fn main () {
179-
* let hello_str = bytes!("Hello, World").to_base64(STANDARD);
180-
* println!("base64 output: {}", hello_str);
181-
* let res = hello_str.from_base64();
182-
* if res.is_ok() {
183-
* let optBytes = str::from_utf8_opt(res.unwrap());
184-
* if optBytes.is_some() {
185-
* println!("decoded from base64: {}", optBytes.unwrap());
186-
* }
187-
* }
179+
* let hello_str = "Hello, World".to_base64(standard);
180+
* println!("{}", hello_str);
181+
* let bytes = hello_str.from_base64();
182+
* println!("{:?}", bytes);
183+
* let result_str = str::from_utf8(bytes);
184+
* println!("{}", result_str);
188185
* }
189186
* ```
190187
*/

branches/try/src/libstd/rt/io/native/file.rs

Lines changed: 230 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,68 +10,273 @@
1010

1111
//! Blocking posix-based file I/O
1212
13+
#[allow(non_camel_case_types)];
14+
15+
use libc;
16+
use os;
1317
use prelude::*;
1418
use super::super::*;
15-
use libc::{c_int, FILE};
1619

17-
#[allow(non_camel_case_types)]
18-
pub type fd_t = c_int;
20+
fn raise_error() {
21+
// XXX: this should probably be a bit more descriptive...
22+
let (kind, desc) = match os::errno() as i32 {
23+
libc::EOF => (EndOfFile, "end of file"),
24+
_ => (OtherIoError, "unknown error"),
25+
};
26+
27+
io_error::cond.raise(IoError {
28+
kind: kind,
29+
desc: desc,
30+
detail: Some(os::last_os_error())
31+
});
32+
}
33+
34+
fn keep_going(data: &[u8], f: &fn(*u8, uint) -> i64) -> i64 {
35+
#[cfg(windows)] static eintr: int = 0; // doesn't matter
36+
#[cfg(not(windows))] static eintr: int = libc::EINTR as int;
37+
38+
let (data, origamt) = do data.as_imm_buf |data, amt| { (data, amt) };
39+
let mut data = data;
40+
let mut amt = origamt;
41+
while amt > 0 {
42+
let mut ret;
43+
loop {
44+
ret = f(data, amt);
45+
if cfg!(not(windows)) { break } // windows has no eintr
46+
// if we get an eintr, then try again
47+
if ret != -1 || os::errno() as int != eintr { break }
48+
}
49+
if ret == 0 {
50+
break
51+
} else if ret != -1 {
52+
amt -= ret as uint;
53+
data = unsafe { data.offset(ret as int) };
54+
} else {
55+
return ret;
56+
}
57+
}
58+
return (origamt - amt) as i64;
59+
}
60+
61+
pub type fd_t = libc::c_int;
1962

2063
pub struct FileDesc {
21-
priv fd: fd_t
64+
priv fd: fd_t,
2265
}
2366

2467
impl FileDesc {
2568
/// Create a `FileDesc` from an open C file descriptor.
2669
///
27-
/// The `FileDesc` takes ownership of the file descriptor
28-
/// and will close it upon destruction.
29-
pub fn new(_fd: fd_t) -> FileDesc { fail2!() }
70+
/// The `FileDesc` will take ownership of the specified file descriptor and
71+
/// close it upon destruction.
72+
///
73+
/// Note that all I/O operations done on this object will be *blocking*, but
74+
/// they do not require the runtime to be active.
75+
pub fn new(fd: fd_t) -> FileDesc {
76+
FileDesc { fd: fd }
77+
}
3078
}
3179

3280
impl Reader for FileDesc {
33-
fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail2!() }
81+
#[fixed_stack_segment] #[inline(never)]
82+
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
83+
#[cfg(windows)] type rlen = libc::c_uint;
84+
#[cfg(not(windows))] type rlen = libc::size_t;
85+
let ret = do keep_going(buf) |buf, len| {
86+
unsafe {
87+
libc::read(self.fd, buf as *mut libc::c_void, len as rlen) as i64
88+
}
89+
};
90+
if ret == 0 {
91+
None
92+
} else if ret < 0 {
93+
raise_error();
94+
None
95+
} else {
96+
Some(ret as uint)
97+
}
98+
}
3499

35-
fn eof(&mut self) -> bool { fail2!() }
100+
fn eof(&mut self) -> bool { false }
36101
}
37102

38103
impl Writer for FileDesc {
39-
fn write(&mut self, _buf: &[u8]) { fail2!() }
104+
#[fixed_stack_segment] #[inline(never)]
105+
fn write(&mut self, buf: &[u8]) {
106+
#[cfg(windows)] type wlen = libc::c_uint;
107+
#[cfg(not(windows))] type wlen = libc::size_t;
108+
let ret = do keep_going(buf) |buf, len| {
109+
unsafe {
110+
libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
111+
}
112+
};
113+
if ret < 0 {
114+
raise_error();
115+
}
116+
}
40117

41-
fn flush(&mut self) { fail2!() }
118+
fn flush(&mut self) {}
42119
}
43120

44-
impl Seek for FileDesc {
45-
fn tell(&self) -> u64 { fail2!() }
46-
47-
fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail2!() }
121+
impl Drop for FileDesc {
122+
#[fixed_stack_segment] #[inline(never)]
123+
fn drop(&mut self) {
124+
unsafe { libc::close(self.fd); }
125+
}
48126
}
49127

50128
pub struct CFile {
51-
priv file: *FILE
129+
priv file: *libc::FILE
52130
}
53131

54132
impl CFile {
55133
/// Create a `CFile` from an open `FILE` pointer.
56134
///
57-
/// The `CFile` takes ownership of the file descriptor
58-
/// and will close it upon destruction.
59-
pub fn new(_file: *FILE) -> CFile { fail2!() }
135+
/// The `CFile` takes ownership of the `FILE` pointer and will close it upon
136+
/// destruction.
137+
pub fn new(file: *libc::FILE) -> CFile { CFile { file: file } }
60138
}
61139

62140
impl Reader for CFile {
63-
fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail2!() }
141+
#[fixed_stack_segment] #[inline(never)]
142+
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
143+
let ret = do keep_going(buf) |buf, len| {
144+
unsafe {
145+
libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
146+
self.file) as i64
147+
}
148+
};
149+
if ret == 0 {
150+
None
151+
} else if ret < 0 {
152+
raise_error();
153+
None
154+
} else {
155+
Some(ret as uint)
156+
}
157+
}
64158

65-
fn eof(&mut self) -> bool { fail2!() }
159+
#[fixed_stack_segment] #[inline(never)]
160+
fn eof(&mut self) -> bool {
161+
unsafe { libc::feof(self.file) != 0 }
162+
}
66163
}
67164

68165
impl Writer for CFile {
69-
fn write(&mut self, _buf: &[u8]) { fail2!() }
166+
#[fixed_stack_segment] #[inline(never)]
167+
fn write(&mut self, buf: &[u8]) {
168+
let ret = do keep_going(buf) |buf, len| {
169+
unsafe {
170+
libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
171+
self.file) as i64
172+
}
173+
};
174+
if ret < 0 {
175+
raise_error();
176+
}
177+
}
70178

71-
fn flush(&mut self) { fail2!() }
179+
#[fixed_stack_segment] #[inline(never)]
180+
fn flush(&mut self) {
181+
if unsafe { libc::fflush(self.file) } < 0 {
182+
raise_error();
183+
}
184+
}
72185
}
73186

74187
impl Seek for CFile {
75-
fn tell(&self) -> u64 { fail2!() }
76-
fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail2!() }
188+
#[fixed_stack_segment] #[inline(never)]
189+
fn tell(&self) -> u64 {
190+
let ret = unsafe { libc::ftell(self.file) };
191+
if ret < 0 {
192+
raise_error();
193+
}
194+
return ret as u64;
195+
}
196+
197+
#[fixed_stack_segment] #[inline(never)]
198+
fn seek(&mut self, pos: i64, style: SeekStyle) {
199+
let whence = match style {
200+
SeekSet => libc::SEEK_SET,
201+
SeekEnd => libc::SEEK_END,
202+
SeekCur => libc::SEEK_CUR,
203+
};
204+
if unsafe { libc::fseek(self.file, pos as libc::c_long, whence) } < 0 {
205+
raise_error();
206+
}
207+
}
208+
}
209+
210+
impl Drop for CFile {
211+
#[fixed_stack_segment] #[inline(never)]
212+
fn drop(&mut self) {
213+
unsafe { libc::fclose(self.file); }
214+
}
215+
}
216+
217+
#[cfg(test)]
218+
mod tests {
219+
use libc;
220+
use os;
221+
use prelude::*;
222+
use rt::io::{io_error, SeekSet};
223+
use super::*;
224+
225+
#[test] #[fixed_stack_segment]
226+
fn test_file_desc() {
227+
// Run this test with some pipes so we don't have to mess around with
228+
// opening or closing files.
229+
unsafe {
230+
let os::Pipe { input, out } = os::pipe();
231+
let mut reader = FileDesc::new(input);
232+
let mut writer = FileDesc::new(out);
233+
234+
writer.write(bytes!("test"));
235+
let mut buf = [0u8, ..4];
236+
match reader.read(buf) {
237+
Some(4) => {
238+
assert_eq!(buf[0], 't' as u8);
239+
assert_eq!(buf[1], 'e' as u8);
240+
assert_eq!(buf[2], 's' as u8);
241+
assert_eq!(buf[3], 't' as u8);
242+
}
243+
r => fail2!("invalid read: {:?}", r)
244+
}
245+
246+
let mut raised = false;
247+
do io_error::cond.trap(|_| { raised = true; }).inside {
248+
writer.read(buf);
249+
}
250+
assert!(raised);
251+
252+
raised = false;
253+
do io_error::cond.trap(|_| { raised = true; }).inside {
254+
reader.write(buf);
255+
}
256+
assert!(raised);
257+
}
258+
}
259+
260+
#[test] #[fixed_stack_segment]
261+
#[ignore(windows)] // apparently windows doesn't like tmpfile
262+
fn test_cfile() {
263+
unsafe {
264+
let f = libc::tmpfile();
265+
assert!(!f.is_null());
266+
let mut file = CFile::new(f);
267+
268+
file.write(bytes!("test"));
269+
let mut buf = [0u8, ..4];
270+
file.seek(0, SeekSet);
271+
match file.read(buf) {
272+
Some(4) => {
273+
assert_eq!(buf[0], 't' as u8);
274+
assert_eq!(buf[1], 'e' as u8);
275+
assert_eq!(buf[2], 's' as u8);
276+
assert_eq!(buf[3], 't' as u8);
277+
}
278+
r => fail2!("invalid read: {:?}", r)
279+
}
280+
}
281+
}
77282
}

0 commit comments

Comments
 (0)