1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 The `io` module contains basic input and output routines.
17 ## `Reader` and `Writer` traits
19 These traits define the minimal set of methods that anything that can do
20 input and output should implement.
22 ## `ReaderUtil` and `WriterUtil` traits
24 Richer methods that allow you to do more. `Reader` only lets you read a certain
25 number of bytes into a buffer, while `ReaderUtil` allows you to read a whole
28 Generally, these richer methods are probably the ones you want to actually
29 use in day-to-day Rust.
31 Furthermore, because there is an implementation of `ReaderUtil` for
32 `<T: Reader>`, when your input or output code implements `Reader`, you get
33 all of these methods for free.
35 ## `print` and `println`
37 These very useful functions are defined here. You generally don't need to
38 import them, though, as the prelude already does.
40 ## `stdin`, `stdout`, and `stderr`
42 These functions return references to the classic three file descriptors. They
43 implement `Reader` and `Writer`, where appropriate.
47 #[allow(missing_doc)];
52 use container::Container;
55 use libc::{c_int, c_long, c_void, size_t, ssize_t};
56 use libc::consts::os::posix88::*;
62 use iterator::IteratorUtil;
66 use str::{StrSlice, OwnedStr, StrUtil};
70 use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
72 #[allow(non_camel_case_types)] // not sure what to do about this
73 pub type fd_t = c_int;
79 #[link_name = "rustrt"]
81 pub unsafe fn rust_get_stdin() -> *libc::FILE;
82 pub unsafe fn rust_get_stdout() -> *libc::FILE;
83 pub unsafe fn rust_get_stderr() -> *libc::FILE;
89 // FIXME (#2004): This is all buffered. We might need an unbuffered variant
92 * The SeekStyle enum describes the relationship between the position
93 * we'd like to seek to from our current position. It's used as an argument
94 * to the `seek` method defined on the `Reader` trait.
96 * There are three seek styles:
98 * 1. `SeekSet` means that the new position should become our position.
99 * 2. `SeekCur` means that we should seek from the current position.
100 * 3. `SeekEnd` means that we should seek from the end.
106 pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
110 * The core Reader trait. All readers must implement this trait.
117 // FIXME (#2004): Seekable really should be orthogonal.
119 // FIXME (#2982): This should probably return an error.
121 * Reads bytes and puts them into `bytes`, advancing the cursor. Returns the
122 * number of bytes read.
124 * The number of bytes to be read is `len` or the end of the file,
125 * whichever comes first.
127 * The buffer must be at least `len` bytes long.
129 * `read` is conceptually similar to C's `fread` function.
135 fn read(&self, bytes: &mut [u8], len: uint) -> uint;
138 * Reads a single byte, advancing the cursor.
140 * In the case of an EOF or an error, returns a negative value.
142 * `read_byte` is conceptually similar to C's `getc` function.
148 fn read_byte(&self) -> int;
151 * Returns a boolean value: are we currently at EOF?
153 * `eof` is conceptually similar to C's `feof` function.
159 fn eof(&self) -> bool;
162 * Seek to a given `position` in the stream.
164 * Takes an optional SeekStyle, which affects how we seek from the
165 * position. See `SeekStyle` docs for more details.
167 * `seek` is conceptually similar to C's `fseek` function.
173 fn seek(&self, position: int, style: SeekStyle);
176 * Returns the current position within the stream.
178 * `tell` is conceptually similar to C's `ftell` function.
184 fn tell(&self) -> uint;
187 impl Reader for @Reader {
188 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
189 self.read(bytes, len)
191 fn read_byte(&self) -> int {
194 fn eof(&self) -> bool {
197 fn seek(&self, position: int, style: SeekStyle) {
198 self.seek(position, style)
200 fn tell(&self) -> uint {
206 * The `ReaderUtil` trait is a home for many of the utility functions
207 * a particular Reader should implement.
209 * The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
210 * on higher-level concepts like 'chars' and 'lines.'
216 pub trait ReaderUtil {
219 * Reads `len` number of bytes, and gives you a new vector back.
225 fn read_bytes(&self, len: uint) -> ~[u8];
228 * Reads up until a specific byte is seen or EOF.
230 * The `include` parameter specifies if the character should be included
231 * in the returned string.
237 fn read_until(&self, c: u8, include: bool) -> ~str;
240 * Reads up until the first '\n' or EOF.
242 * The '\n' is not included in the result.
248 fn read_line(&self) -> ~str;
253 * Assumes that those chars are UTF-8 encoded.
255 * The '\n' is not included in the result.
261 fn read_chars(&self, n: uint) -> ~[char];
264 * Reads a single UTF-8 encoded char.
270 fn read_char(&self) -> char;
273 * Reads up until the first null byte or EOF.
275 * The null byte is not returned.
281 fn read_c_str(&self) -> ~str;
284 * Reads all remaining data in the stream.
290 fn read_whole_stream(&self) -> ~[u8];
293 * Iterate over every byte until EOF or the iterator breaks.
299 fn each_byte(&self, it: &fn(int) -> bool) -> bool;
302 * Iterate over every char until EOF or the iterator breaks.
308 fn each_char(&self, it: &fn(char) -> bool) -> bool;
311 * Iterate over every line until EOF or the iterator breaks.
317 fn each_line(&self, it: &fn(&str) -> bool) -> bool;
320 * Reads all of the lines in the stream.
322 * Returns a vector of those lines.
328 fn read_lines(&self) -> ~[~str];
331 * Reads `n` little-endian unsigned integer bytes.
333 * `n` must be between 1 and 8, inclusive.
339 fn read_le_uint_n(&self, nbytes: uint) -> u64;
342 * Reads `n` little-endian signed integer bytes.
344 * `n` must be between 1 and 8, inclusive.
350 fn read_le_int_n(&self, nbytes: uint) -> i64;
353 * Reads `n` big-endian unsigned integer bytes.
355 * `n` must be between 1 and 8, inclusive.
361 fn read_be_uint_n(&self, nbytes: uint) -> u64;
364 * Reads `n` big-endian signed integer bytes.
366 * `n` must be between 1 and 8, inclusive.
372 fn read_be_int_n(&self, nbytes: uint) -> i64;
375 * Reads a little-endian unsigned integer.
377 * The number of bytes returned is system-dependant.
383 fn read_le_uint(&self) -> uint;
386 * Reads a little-endian integer.
388 * The number of bytes returned is system-dependant.
394 fn read_le_int(&self) -> int;
397 * Reads a big-endian unsigned integer.
399 * The number of bytes returned is system-dependant.
405 fn read_be_uint(&self) -> uint;
408 * Reads a big-endian integer.
410 * The number of bytes returned is system-dependant.
416 fn read_be_int(&self) -> int;
419 * Reads a big-endian `u64`.
421 * `u64`s are 8 bytes long.
427 fn read_be_u64(&self) -> u64;
430 * Reads a big-endian `u32`.
432 * `u32`s are 4 bytes long.
438 fn read_be_u32(&self) -> u32;
441 * Reads a big-endian `u16`.
443 * `u16`s are 2 bytes long.
449 fn read_be_u16(&self) -> u16;
452 * Reads a big-endian `i64`.
454 * `i64`s are 8 bytes long.
460 fn read_be_i64(&self) -> i64;
463 * Reads a big-endian `i32`.
465 * `i32`s are 4 bytes long.
471 fn read_be_i32(&self) -> i32;
474 * Reads a big-endian `i16`.
476 * `i16`s are 2 bytes long.
482 fn read_be_i16(&self) -> i16;
485 * Reads a big-endian `f64`.
487 * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
493 fn read_be_f64(&self) -> f64;
496 * Reads a big-endian `f32`.
498 * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
504 fn read_be_f32(&self) -> f32;
507 * Reads a little-endian `u64`.
509 * `u64`s are 8 bytes long.
515 fn read_le_u64(&self) -> u64;
518 * Reads a little-endian `u32`.
520 * `u32`s are 4 bytes long.
526 fn read_le_u32(&self) -> u32;
529 * Reads a little-endian `u16`.
531 * `u16`s are 2 bytes long.
537 fn read_le_u16(&self) -> u16;
540 * Reads a little-endian `i64`.
542 * `i64`s are 8 bytes long.
548 fn read_le_i64(&self) -> i64;
551 * Reads a little-endian `i32`.
553 * `i32`s are 4 bytes long.
559 fn read_le_i32(&self) -> i32;
562 * Reads a little-endian `i16`.
564 * `i16`s are 2 bytes long.
570 fn read_le_i16(&self) -> i16;
573 * Reads a little-endian `f64`.
575 * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
581 fn read_le_f64(&self) -> f64;
584 * Reads a little-endian `f32`.
586 * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
592 fn read_le_f32(&self) -> f32;
603 fn read_u8(&self) -> u8;
614 fn read_i8(&self) -> i8;
617 impl<T:Reader> ReaderUtil for T {
619 fn read_bytes(&self,len: uint) -> ~[u8] {
620 let mut bytes = vec::with_capacity(len);
621 unsafe { vec::raw::set_len(&mut bytes, len); }
623 let count = self.read(bytes, len);
625 unsafe { vec::raw::set_len(&mut bytes, count); }
629 fn read_until(&self, c: u8, include: bool) -> ~str {
632 let ch = self.read_byte();
633 if ch == -1 || ch == c as int {
634 if include && ch == c as int {
635 bytes.push(ch as u8);
639 bytes.push(ch as u8);
641 str::from_bytes(bytes)
644 fn read_line(&self) -> ~str {
645 self.read_until('\n' as u8, false)
648 fn read_chars(&self, n: uint) -> ~[char] {
649 // returns the (consumed offset, n_req), appends characters to &chars
650 fn chars_from_bytes<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
653 let bytes_len = bytes.len();
654 while i < bytes_len {
656 let w = str::utf8_char_width(b0);
661 chars.push(b0 as char);
664 // can't satisfy this char with the existing data
666 return (i - 1, end - bytes_len);
670 let next = bytes[i] as int;
672 assert!((next > -1));
673 assert_eq!(next & 192, 128);
675 val += (next & 63) as uint;
677 // See str::StrSlice::char_at
678 val += ((b0 << ((w + 1) as u8)) as uint)
679 << (w - 1) * 6 - w - 1u;
680 chars.push(val as char);
686 // might need more bytes, but reading n will never over-read
689 let data = self.read_bytes(nbread);
691 // eof - FIXME (#2004): should we do something if
692 // we're split in a unicode char?
695 bytes.push_all(data);
696 let (offset, nbreq) = chars_from_bytes::<T>(&bytes, &mut chars);
697 let ncreq = n - chars.len();
698 // again we either know we need a certain number of bytes
699 // to complete a character, or we make sure we don't
700 // over-read by reading 1-byte per char needed
701 nbread = if ncreq > nbreq { ncreq } else { nbreq };
703 bytes = bytes.slice(offset, bytes.len()).to_owned();
709 fn read_char(&self) -> char {
710 let c = self.read_chars(1);
712 return -1 as char; // FIXME will this stay valid? // #2004
714 assert_eq!(c.len(), 1);
718 fn read_c_str(&self) -> ~str {
719 self.read_until(0u8, false)
722 fn read_whole_stream(&self) -> ~[u8] {
723 let mut bytes: ~[u8] = ~[];
724 while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
728 fn each_byte(&self, it: &fn(int) -> bool) -> bool {
730 if !it(self.read_byte()) { return false; }
735 fn each_char(&self, it: &fn(char) -> bool) -> bool {
737 if !it(self.read_char()) { return false; }
742 fn each_line(&self, it: &fn(s: &str) -> bool) -> bool {
744 // include the \n, so that we can distinguish an entirely empty
745 // line read after "...\n", and the trailing empty line in
747 let mut line = self.read_until('\n' as u8, true);
749 // blank line at the end of the reader is ignored
750 if self.eof() && line.is_empty() { break; }
752 // trim the \n, so that each_line is consistent with read_line
754 if line[n-1] == '\n' as u8 {
755 unsafe { str::raw::set_len(&mut line, n-1); }
758 if !it(line) { return false; }
763 fn read_lines(&self) -> ~[~str] {
764 do vec::build |push| {
765 for self.each_line |line| {
766 push(str::to_owned(line));
771 // FIXME int reading methods need to deal with eof - issue #2004
773 fn read_le_uint_n(&self, nbytes: uint) -> u64 {
774 assert!(nbytes > 0 && nbytes <= 8);
780 val += (self.read_u8() as u64) << pos;
787 fn read_le_int_n(&self, nbytes: uint) -> i64 {
788 extend_sign(self.read_le_uint_n(nbytes), nbytes)
791 fn read_be_uint_n(&self, nbytes: uint) -> u64 {
792 assert!(nbytes > 0 && nbytes <= 8);
798 val += (self.read_u8() as u64) << i * 8;
803 fn read_be_int_n(&self, nbytes: uint) -> i64 {
804 extend_sign(self.read_be_uint_n(nbytes), nbytes)
807 fn read_le_uint(&self) -> uint {
808 self.read_le_uint_n(uint::bytes) as uint
811 fn read_le_int(&self) -> int {
812 self.read_le_int_n(int::bytes) as int
815 fn read_be_uint(&self) -> uint {
816 self.read_be_uint_n(uint::bytes) as uint
819 fn read_be_int(&self) -> int {
820 self.read_be_int_n(int::bytes) as int
823 fn read_be_u64(&self) -> u64 {
824 self.read_be_uint_n(8) as u64
827 fn read_be_u32(&self) -> u32 {
828 self.read_be_uint_n(4) as u32
831 fn read_be_u16(&self) -> u16 {
832 self.read_be_uint_n(2) as u16
835 fn read_be_i64(&self) -> i64 {
836 self.read_be_int_n(8) as i64
839 fn read_be_i32(&self) -> i32 {
840 self.read_be_int_n(4) as i32
843 fn read_be_i16(&self) -> i16 {
844 self.read_be_int_n(2) as i16
847 fn read_be_f64(&self) -> f64 {
849 cast::transmute::<u64, f64>(self.read_be_u64())
853 fn read_be_f32(&self) -> f32 {
855 cast::transmute::<u32, f32>(self.read_be_u32())
859 fn read_le_u64(&self) -> u64 {
860 self.read_le_uint_n(8) as u64
863 fn read_le_u32(&self) -> u32 {
864 self.read_le_uint_n(4) as u32
867 fn read_le_u16(&self) -> u16 {
868 self.read_le_uint_n(2) as u16
871 fn read_le_i64(&self) -> i64 {
872 self.read_le_int_n(8) as i64
875 fn read_le_i32(&self) -> i32 {
876 self.read_le_int_n(4) as i32
879 fn read_le_i16(&self) -> i16 {
880 self.read_le_int_n(2) as i16
883 fn read_le_f64(&self) -> f64 {
885 cast::transmute::<u64, f64>(self.read_le_u64())
889 fn read_le_f32(&self) -> f32 {
891 cast::transmute::<u32, f32>(self.read_le_u32())
895 fn read_u8(&self) -> u8 {
896 self.read_byte() as u8
899 fn read_i8(&self) -> i8 {
900 self.read_byte() as i8
904 fn extend_sign(val: u64, nbytes: uint) -> i64 {
905 let shift = (8 - nbytes) * 8;
906 (val << shift) as i64 >> shift
909 // Reader implementations
911 fn convert_whence(whence: SeekStyle) -> i32 {
912 return match whence {
919 impl Reader for *libc::FILE {
920 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
922 do bytes.as_mut_buf |buf_p, buf_len| {
923 assert!(buf_len >= len);
925 let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
926 len as size_t, *self) as uint;
928 match libc::ferror(*self) {
931 error!("error reading buffer");
932 error!("%s", os::last_os_error());
942 fn read_byte(&self) -> int {
944 libc::fgetc(*self) as int
947 fn eof(&self) -> bool {
949 return libc::feof(*self) != 0 as c_int;
952 fn seek(&self, offset: int, whence: SeekStyle) {
954 assert!(libc::fseek(*self,
956 convert_whence(whence)) == 0 as c_int);
959 fn tell(&self) -> uint {
961 return libc::ftell(*self) as uint;
966 struct Wrapper<T, C> {
971 // A forwarding impl of reader that also holds on to a resource for the
972 // duration of its lifetime.
973 // FIXME there really should be a better way to do this // #2004
974 impl<R:Reader,C> Reader for Wrapper<R, C> {
975 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
976 self.base.read(bytes, len)
978 fn read_byte(&self) -> int { self.base.read_byte() }
979 fn eof(&self) -> bool { self.base.eof() }
980 fn seek(&self, off: int, whence: SeekStyle) {
981 self.base.seek(off, whence)
983 fn tell(&self) -> uint { self.base.tell() }
991 pub fn new(f: *libc::FILE) -> FILERes {
996 impl Drop for FILERes {
999 libc::fclose(self.f);
1004 pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
1006 @Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader
1012 // FIXME (#2004): this should either be an trait-less impl, a set of
1013 // top-level functions that take a reader, or a set of default methods on
1014 // reader (which can then be called reader)
1017 * Gives a `Reader` that allows you to read values from standard input.
1022 * let stdin = core::io::stdin();
1023 * let line = stdin.read_line();
1024 * core::io::print(line);
1027 pub fn stdin() -> @Reader {
1029 @rustrt::rust_get_stdin() as @Reader
1033 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
1034 let f = do path.to_str().as_c_str |pathbuf| {
1035 do "r".as_c_str |modebuf| {
1036 unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
1040 if f as uint == 0u {
1041 result::Err(~"error opening " + path.to_str())
1043 result::Ok(FILE_reader(f, true))
1049 pub struct BytesReader {
1050 // FIXME(#5723) see other FIXME below
1051 // FIXME(#7268) this should also be parameterized over <'self>
1052 bytes: &'static [u8],
1056 impl Reader for BytesReader {
1057 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
1058 let count = num::min(len, self.bytes.len() - *self.pos);
1060 let view = self.bytes.slice(*self.pos, self.bytes.len());
1061 vec::bytes::copy_memory(bytes, view, count);
1068 fn read_byte(&self) -> int {
1069 if *self.pos == self.bytes.len() {
1073 let b = self.bytes[*self.pos];
1078 fn eof(&self) -> bool {
1079 *self.pos == self.bytes.len()
1082 fn seek(&self, offset: int, whence: SeekStyle) {
1083 let pos = *self.pos;
1084 *self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
1087 fn tell(&self) -> uint {
1092 pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
1093 // XXX XXX XXX this is glaringly unsound
1094 // FIXME(#5723) Use a &Reader for the callback's argument. Should be:
1095 // fn with_bytes_reader<'r, T>(bytes: &'r [u8], f: &fn(&'r Reader) -> T) -> T
1096 let bytes: &'static [u8] = unsafe { cast::transmute(bytes) };
1103 pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
1104 // FIXME(#5723): As above.
1105 with_bytes_reader(s.as_bytes(), f)
1109 pub enum FileFlag { Append, Create, Truncate, NoFlag, }
1111 // What type of writer are we?
1113 pub enum WriterType { Screen, File }
1115 // FIXME (#2004): Seekable really should be orthogonal.
1116 // FIXME (#2004): eventually u64
1117 /// The raw underlying writer trait. All writers must implement this.
1120 /// Write all of the given bytes.
1121 fn write(&self, v: &[u8]);
1123 /// Move the current position within the stream. The second parameter
1124 /// determines the position that the first parameter is relative to.
1125 fn seek(&self, int, SeekStyle);
1127 /// Return the current position within the stream.
1128 fn tell(&self) -> uint;
1130 /// Flush the output buffer for this stream (if there is one).
1131 fn flush(&self) -> int;
1133 /// Determine if this Writer is writing to a file or not.
1134 fn get_type(&self) -> WriterType;
1137 impl Writer for @Writer {
1138 fn write(&self, v: &[u8]) { self.write(v) }
1139 fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
1140 fn tell(&self) -> uint { self.tell() }
1141 fn flush(&self) -> int { self.flush() }
1142 fn get_type(&self) -> WriterType { self.get_type() }
1145 impl<W:Writer,C> Writer for Wrapper<W, C> {
1146 fn write(&self, bs: &[u8]) { self.base.write(bs); }
1147 fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
1148 fn tell(&self) -> uint { self.base.tell() }
1149 fn flush(&self) -> int { self.base.flush() }
1150 fn get_type(&self) -> WriterType { File }
1153 impl Writer for *libc::FILE {
1154 fn write(&self, v: &[u8]) {
1156 do v.as_imm_buf |vbuf, len| {
1157 let nout = libc::fwrite(vbuf as *c_void,
1161 if nout != len as size_t {
1162 error!("error writing buffer");
1163 error!("%s", os::last_os_error());
1169 fn seek(&self, offset: int, whence: SeekStyle) {
1171 assert!(libc::fseek(*self,
1173 convert_whence(whence)) == 0 as c_int);
1176 fn tell(&self) -> uint {
1178 libc::ftell(*self) as uint
1181 fn flush(&self) -> int {
1183 libc::fflush(*self) as int
1186 fn get_type(&self) -> WriterType {
1188 let fd = libc::fileno(*self);
1189 if libc::isatty(fd) == 0 { File }
1195 pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
1197 @Wrapper { base: f, cleanup: FILERes::new(f) } as @Writer
1203 impl Writer for fd_t {
1204 fn write(&self, v: &[u8]) {
1207 do v.as_imm_buf |vbuf, len| {
1209 let vb = ptr::offset(vbuf, count) as *c_void;
1210 let nout = libc::write(*self, vb, len as size_t);
1211 if nout < 0 as ssize_t {
1212 error!("error writing buffer");
1213 error!("%s", os::last_os_error());
1216 count += nout as uint;
1221 fn seek(&self, _offset: int, _whence: SeekStyle) {
1222 error!("need 64-bit foreign calls for seek, sorry");
1225 fn tell(&self) -> uint {
1226 error!("need 64-bit foreign calls for tell, sorry");
1229 fn flush(&self) -> int { 0 }
1230 fn get_type(&self) -> WriterType {
1232 if libc::isatty(*self) == 0 { File } else { Screen }
1242 pub fn new(fd: fd_t) -> FdRes {
1247 impl Drop for FdRes {
1250 libc::close(self.fd);
1255 pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
1257 @Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer
1264 pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
1265 -> Result<@Writer, ~str> {
1268 (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
1272 fn wb() -> c_int { O_WRONLY as c_int }
1274 let mut fflags: c_int = wb();
1275 for flags.iter().advance |f| {
1277 Append => fflags |= O_APPEND as c_int,
1278 Create => fflags |= O_CREAT as c_int,
1279 Truncate => fflags |= O_TRUNC as c_int,
1284 do path.to_str().as_c_str |pathbuf| {
1285 libc::open(pathbuf, fflags,
1286 (S_IRUSR | S_IWUSR) as c_int)
1289 if fd < (0 as c_int) {
1290 result::Err(fmt!("error opening %s: %s", path.to_str(),
1291 os::last_os_error()))
1293 result::Ok(fd_writer(fd, true))
1297 pub fn u64_to_le_bytes<T>(n: u64, size: uint,
1298 f: &fn(v: &[u8]) -> T) -> T {
1299 assert!(size <= 8u);
1301 1u => f(&[n as u8]),
1318 let mut bytes: ~[u8] = ~[];
1322 bytes.push((n & 255_u64) as u8);
1331 pub fn u64_to_be_bytes<T>(n: u64, size: uint,
1332 f: &fn(v: &[u8]) -> T) -> T {
1333 assert!(size <= 8u);
1335 1u => f(&[n as u8]),
1336 2u => f(&[(n >> 8) as u8,
1338 4u => f(&[(n >> 24) as u8,
1342 8u => f(&[(n >> 56) as u8,
1351 let mut bytes: ~[u8] = ~[];
1354 let shift = ((i - 1u) * 8u) as u64;
1355 bytes.push((n >> shift) as u8);
1363 pub fn u64_from_be_bytes(data: &[u8],
1368 assert!((sz <= 8u));
1369 let mut val = 0_u64;
1370 let mut pos = start;
1373 val += (data[pos] as u64) << ((sz * 8u) as u64);
1379 // FIXME: #3048 combine trait+impl (or just move these to
1380 // default methods on writer)
1381 /// Generic utility functions defined on writers.
1382 pub trait WriterUtil {
1384 /// Write a single utf-8 encoded char.
1385 fn write_char(&self, ch: char);
1387 /// Write every char in the given str, encoded as utf-8.
1388 fn write_str(&self, s: &str);
1390 /// Write the given str, as utf-8, followed by '\n'.
1391 fn write_line(&self, s: &str);
1393 /// Write the result of passing n through `int::to_str_bytes`.
1394 fn write_int(&self, n: int);
1396 /// Write the result of passing n through `uint::to_str_bytes`.
1397 fn write_uint(&self, n: uint);
1399 /// Write a little-endian uint (number of bytes depends on system).
1400 fn write_le_uint(&self, n: uint);
1402 /// Write a little-endian int (number of bytes depends on system).
1403 fn write_le_int(&self, n: int);
1405 /// Write a big-endian uint (number of bytes depends on system).
1406 fn write_be_uint(&self, n: uint);
1408 /// Write a big-endian int (number of bytes depends on system).
1409 fn write_be_int(&self, n: int);
1411 /// Write a big-endian u64 (8 bytes).
1412 fn write_be_u64(&self, n: u64);
1414 /// Write a big-endian u32 (4 bytes).
1415 fn write_be_u32(&self, n: u32);
1417 /// Write a big-endian u16 (2 bytes).
1418 fn write_be_u16(&self, n: u16);
1420 /// Write a big-endian i64 (8 bytes).
1421 fn write_be_i64(&self, n: i64);
1423 /// Write a big-endian i32 (4 bytes).
1424 fn write_be_i32(&self, n: i32);
1426 /// Write a big-endian i16 (2 bytes).
1427 fn write_be_i16(&self, n: i16);
1429 /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
1430 fn write_be_f64(&self, f: f64);
1432 /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
1433 fn write_be_f32(&self, f: f32);
1435 /// Write a little-endian u64 (8 bytes).
1436 fn write_le_u64(&self, n: u64);
1438 /// Write a little-endian u32 (4 bytes).
1439 fn write_le_u32(&self, n: u32);
1441 /// Write a little-endian u16 (2 bytes).
1442 fn write_le_u16(&self, n: u16);
1444 /// Write a little-endian i64 (8 bytes).
1445 fn write_le_i64(&self, n: i64);
1447 /// Write a little-endian i32 (4 bytes).
1448 fn write_le_i32(&self, n: i32);
1450 /// Write a little-endian i16 (2 bytes).
1451 fn write_le_i16(&self, n: i16);
1453 /// Write a little-endian IEEE754 double-precision floating-point
1455 fn write_le_f64(&self, f: f64);
1457 /// Write a litten-endian IEEE754 single-precision floating-point
1459 fn write_le_f32(&self, f: f32);
1461 /// Write a u8 (1 byte).
1462 fn write_u8(&self, n: u8);
1464 /// Write a i8 (1 byte).
1465 fn write_i8(&self, n: i8);
1468 impl<T:Writer> WriterUtil for T {
1469 fn write_char(&self, ch: char) {
1470 if (ch as uint) < 128u {
1471 self.write(&[ch as u8]);
1473 self.write_str(str::from_char(ch));
1476 fn write_str(&self, s: &str) { self.write(s.as_bytes()) }
1477 fn write_line(&self, s: &str) {
1479 self.write_str(&"\n");
1481 fn write_int(&self, n: int) {
1482 int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1484 fn write_uint(&self, n: uint) {
1485 uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1487 fn write_le_uint(&self, n: uint) {
1488 u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
1490 fn write_le_int(&self, n: int) {
1491 u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
1493 fn write_be_uint(&self, n: uint) {
1494 u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
1496 fn write_be_int(&self, n: int) {
1497 u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
1499 fn write_be_u64(&self, n: u64) {
1500 u64_to_be_bytes(n, 8u, |v| self.write(v))
1502 fn write_be_u32(&self, n: u32) {
1503 u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1505 fn write_be_u16(&self, n: u16) {
1506 u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1508 fn write_be_i64(&self, n: i64) {
1509 u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
1511 fn write_be_i32(&self, n: i32) {
1512 u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1514 fn write_be_i16(&self, n: i16) {
1515 u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1517 fn write_be_f64(&self, f:f64) {
1519 self.write_be_u64(cast::transmute(f))
1522 fn write_be_f32(&self, f:f32) {
1524 self.write_be_u32(cast::transmute(f))
1527 fn write_le_u64(&self, n: u64) {
1528 u64_to_le_bytes(n, 8u, |v| self.write(v))
1530 fn write_le_u32(&self, n: u32) {
1531 u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1533 fn write_le_u16(&self, n: u16) {
1534 u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1536 fn write_le_i64(&self, n: i64) {
1537 u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
1539 fn write_le_i32(&self, n: i32) {
1540 u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1542 fn write_le_i16(&self, n: i16) {
1543 u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1545 fn write_le_f64(&self, f:f64) {
1547 self.write_le_u64(cast::transmute(f))
1550 fn write_le_f32(&self, f:f32) {
1552 self.write_le_u32(cast::transmute(f))
1556 fn write_u8(&self, n: u8) { self.write([n]) }
1557 fn write_i8(&self, n: i8) { self.write([n as u8]) }
1561 pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
1562 mk_file_writer(path, flags).chain(|w| result::Ok(w))
1566 // FIXME: fileflags // #2004
1567 pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
1569 let f = do path.to_str().as_c_str |pathbuf| {
1570 do "w".as_c_str |modebuf| {
1571 libc::fopen(pathbuf, modebuf)
1574 return if f as uint == 0u {
1575 result::Err(~"error opening " + path.to_str())
1577 result::Ok(FILE_writer(f, true))
1582 // FIXME (#2004) it would be great if this could be a const
1583 // FIXME (#2004) why are these different from the way stdin() is
1588 * Gives a `Writer` which allows you to write to the standard output.
1593 * let stdout = core::io::stdout();
1594 * stdout.write_str("hello\n");
1597 pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
1600 * Gives a `Writer` which allows you to write to standard error.
1605 * let stderr = core::io::stderr();
1606 * stderr.write_str("hello\n");
1609 pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
1612 * Prints a string to standard output.
1614 * This string will not have an implicit newline at the end. If you want
1615 * an implicit newline, please see `println`.
1620 * // print is imported into the prelude, and so is always available.
1624 pub fn print(s: &str) {
1625 stdout().write_str(s);
1629 * Prints a string to standard output, followed by a newline.
1631 * If you do not want an implicit newline, please see `print`.
1636 * // println is imported into the prelude, and so is always available.
1640 pub fn println(s: &str) {
1641 stdout().write_line(s);
1644 pub struct BytesWriter {
1650 pub fn new() -> BytesWriter {
1658 impl Writer for BytesWriter {
1659 fn write(&self, v: &[u8]) {
1660 let v_len = v.len();
1662 let bytes = &mut *self.bytes;
1663 let count = num::max(bytes.len(), *self.pos + v_len);
1664 bytes.reserve(count);
1667 vec::raw::set_len(bytes, count);
1669 let view = bytes.mut_slice(*self.pos, count);
1670 vec::bytes::copy_memory(view, v, v_len);
1676 fn seek(&self, offset: int, whence: SeekStyle) {
1677 let pos = *self.pos;
1678 let len = self.bytes.len();
1679 *self.pos = seek_in_buf(offset, pos, len, whence);
1682 fn tell(&self) -> uint {
1686 fn flush(&self) -> int {
1690 fn get_type(&self) -> WriterType {
1695 pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
1696 let wr = @BytesWriter::new();
1698 let @BytesWriter { bytes, _ } = wr;
1702 pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
1703 let mut v = with_bytes_writer(f);
1705 // Make sure the vector has a trailing null and is proper utf8.
1707 assert!(str::is_utf8(v));
1710 ::cast::transmute(v)
1714 // Utility functions
1715 pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
1717 let mut bpos = pos as int;
1718 let blen = len as int;
1720 SeekSet => bpos = offset,
1721 SeekCur => bpos += offset,
1722 SeekEnd => bpos = blen + offset
1724 if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
1725 return bpos as uint;
1728 pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
1729 result::chain(read_whole_file(file), |bytes| {
1730 if str::is_utf8(bytes) {
1731 result::Ok(str::from_bytes(bytes))
1733 result::Err(file.to_str() + " is not UTF-8")
1738 // FIXME (#2004): implement this in a low-level way. Going through the
1739 // abstractions is pointless.
1740 pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
1741 result::chain(file_reader(file), |rdr| {
1742 result::Ok(rdr.read_whole_stream())
1749 use io::{FILERes, FdRes, fd_t};
1752 use option::{None, Option, Some};
1756 // whatever fsync does on that platform
1759 // fdatasync on linux, similiar or more on other platforms
1764 // You must additionally sync the parent directory as well!
1769 // Artifacts that need to fsync on destruction
1775 pub fn new(arg: Arg<t>) -> Res<t> {
1780 #[unsafe_destructor]
1781 impl<T> Drop for Res<T> {
1783 match self.arg.opt_level {
1786 // fail hard if not succesful
1787 assert!(((self.arg.fsync_fn)(&self.arg.val, level) != -1));
1795 opt_level: Option<Level>,
1796 fsync_fn: @fn(f: &t, Level) -> int,
1799 // fsync file after executing blk
1800 // FIXME (#2004) find better way to create resources within lifetime of
1802 pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
1803 blk: &fn(v: Res<*libc::FILE>)) {
1805 val: file.f, opt_level: opt_level,
1806 fsync_fn: |file, l| {
1808 os::fsync_fd(libc::fileno(*file), l) as int
1814 // fsync fd after executing blk
1815 pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
1816 blk: &fn(v: Res<fd_t>)) {
1818 val: fd.fd, opt_level: opt_level,
1819 fsync_fn: |fd, l| os::fsync_fd(*fd, l) as int
1823 // Type of objects that may want to fsync
1824 pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
1826 // Call o.fsync after executing blk
1827 pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
1828 blk: &fn(v: Res<@FSyncable>)) {
1830 val: o, opt_level: opt_level,
1831 fsync_fn: |o, l| (*o).fsync(l)
1839 use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
1848 let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
1851 ~"A hoopy frood who really knows where his towel is.";
1852 debug!(frood.clone());
1854 let out: @io::Writer =
1856 io::file_writer(tmpfile, [io::Create, io::Truncate]));
1857 out.write_str(frood);
1859 let inp: @io::Reader = result::unwrap(io::file_reader(tmpfile));
1860 let frood2: ~str = inp.read_c_str();
1861 debug!(frood2.clone());
1862 assert_eq!(frood, frood2);
1866 fn test_readchars_empty() {
1867 do io::with_str_reader("") |inp| {
1868 let res : ~[char] = inp.read_chars(128);
1869 assert_eq!(res.len(), 0);
1874 fn test_read_line_utf8() {
1875 do io::with_str_reader("生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
1876 let line = inp.read_line();
1877 assert_eq!(line, ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤");
1882 fn test_read_lines() {
1883 do io::with_str_reader("a\nb\nc\n") |inp| {
1884 assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
1887 do io::with_str_reader("a\nb\nc") |inp| {
1888 assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
1891 do io::with_str_reader("") |inp| {
1892 assert!(inp.read_lines().is_empty());
1897 fn test_readchars_wide() {
1898 let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
1899 let ivals : ~[int] = ~[
1900 29983, 38152, 30340, 27748,
1901 21273, 20999, 32905, 27748,
1902 104, 101, 108, 108, 111,
1903 29983, 38152, 30340, 27748,
1904 21273, 20999, 32905, 27748];
1905 fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
1906 do io::with_str_reader(s) |inp| {
1907 let res : ~[char] = inp.read_chars(len);
1908 if len <= ivals.len() {
1909 assert_eq!(res.len(), len);
1911 for ivals.iter().zip(res.iter()).advance |(iv, c)| {
1912 assert!(*iv == *c as int)
1918 check_read_ln(i, wide_test, ivals);
1921 // check a long read for good measure
1922 check_read_ln(128, wide_test, ivals);
1926 fn test_readchar() {
1927 do io::with_str_reader("生") |inp| {
1928 let res : char = inp.read_char();
1929 assert_eq!(res as int, 29983);
1934 fn test_readchar_empty() {
1935 do io::with_str_reader("") |inp| {
1936 let res : char = inp.read_char();
1937 assert_eq!(res as int, -1);
1942 fn file_reader_not_exist() {
1943 match io::file_reader(&Path("not a file")) {
1945 assert_eq!(e, ~"error opening not a file");
1947 result::Ok(_) => fail!()
1953 #[ignore(cfg(windows))]
1954 fn test_read_buffer_too_small() {
1955 let path = &Path("tmp/lib-io-test-read-buffer-too-small.tmp");
1956 // ensure the file exists
1957 io::file_writer(path, [io::Create]).unwrap();
1959 let file = io::file_reader(path).unwrap();
1960 let mut buf = vec::from_elem(5, 0u8);
1961 file.read(buf, 6); // this should fail because buf is too small
1965 fn test_read_buffer_big_enough() {
1966 let path = &Path("tmp/lib-io-test-read-buffer-big-enough.tmp");
1967 // ensure the file exists
1968 io::file_writer(path, [io::Create]).unwrap();
1970 let file = io::file_reader(path).unwrap();
1971 let mut buf = vec::from_elem(5, 0u8);
1972 file.read(buf, 4); // this should succeed because buf is big enough
1976 fn test_write_empty() {
1977 let file = io::file_writer(&Path("tmp/lib-io-test-write-empty.tmp"),
1978 [io::Create]).unwrap();
1983 fn file_writer_bad_name() {
1984 match io::file_writer(&Path("?/?"), []) {
1986 assert!(e.starts_with("error opening"));
1988 result::Ok(_) => fail!()
1993 fn buffered_file_writer_bad_name() {
1994 match io::buffered_file_writer(&Path("?/?")) {
1996 assert!(e.starts_with("error opening"));
1998 result::Ok(_) => fail!()
2003 fn bytes_buffer_overwrite() {
2004 let wr = BytesWriter::new();
2005 wr.write([0u8, 1u8, 2u8, 3u8]);
2006 assert!(*wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
2007 wr.seek(-2, SeekCur);
2008 wr.write([4u8, 5u8, 6u8, 7u8]);
2009 assert!(*wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
2010 wr.seek(-2, SeekEnd);
2012 wr.seek(1, SeekSet);
2014 assert!(*wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
2018 fn test_read_write_le() {
2019 let path = Path("tmp/lib-io-test-read-write-le.tmp");
2020 let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
2022 // write the ints to the file
2024 let file = io::file_writer(&path, [io::Create]).unwrap();
2025 for uints.iter().advance |i| {
2026 file.write_le_u64(*i);
2030 // then read them back and check that they are the same
2032 let file = io::file_reader(&path).unwrap();
2033 for uints.iter().advance |i| {
2034 assert_eq!(file.read_le_u64(), *i);
2040 fn test_read_write_be() {
2041 let path = Path("tmp/lib-io-test-read-write-be.tmp");
2042 let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
2044 // write the ints to the file
2046 let file = io::file_writer(&path, [io::Create]).unwrap();
2047 for uints.iter().advance |i| {
2048 file.write_be_u64(*i);
2052 // then read them back and check that they are the same
2054 let file = io::file_reader(&path).unwrap();
2055 for uints.iter().advance |i| {
2056 assert_eq!(file.read_be_u64(), *i);
2062 fn test_read_be_int_n() {
2063 let path = Path("tmp/lib-io-test-read-be-int-n.tmp");
2064 let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
2066 // write the ints to the file
2068 let file = io::file_writer(&path, [io::Create]).unwrap();
2069 for ints.iter().advance |i| {
2070 file.write_be_i32(*i);
2074 // then read them back and check that they are the same
2076 let file = io::file_reader(&path).unwrap();
2077 for ints.iter().advance |i| {
2078 // this tests that the sign extension is working
2079 // (comparing the values as i32 would not test this)
2080 assert_eq!(file.read_be_int_n(4), *i as i64);
2086 fn test_read_f32() {
2087 let path = Path("tmp/lib-io-test-read-f32.tmp");
2088 //big-endian floating-point 8.1250
2089 let buf = ~[0x41, 0x02, 0x00, 0x00];
2092 let file = io::file_writer(&path, [io::Create]).unwrap();
2097 let file = io::file_reader(&path).unwrap();
2098 let f = file.read_be_f32();
2099 assert_eq!(f, 8.1250);
2104 fn test_read_write_f32() {
2105 let path = Path("tmp/lib-io-test-read-write-f32.tmp");
2109 let file = io::file_writer(&path, [io::Create]).unwrap();
2110 file.write_be_f32(f);
2111 file.write_le_f32(f);
2115 let file = io::file_reader(&path).unwrap();
2116 assert_eq!(file.read_be_f32(), 8.1250);
2117 assert_eq!(file.read_le_f32(), 8.1250);