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.
21 use libc::{c_int, c_long, c_void, size_t, ssize_t};
22 use libc::consts::os::posix88::*;
33 #[allow(non_camel_case_types)] // not sure what to do about this
34 pub type fd_t = c_int;
40 #[link_name = "rustrt"]
42 unsafe fn rust_get_stdin() -> *libc::FILE;
43 unsafe fn rust_get_stdout() -> *libc::FILE;
44 unsafe fn rust_get_stderr() -> *libc::FILE;
50 // FIXME (#2004): This is all buffered. We might need an unbuffered variant
53 * The SeekStyle enum describes the relationship between the position
54 * we'd like to seek to from our current position. It's used as an argument
55 * to the `seek` method defined on the `Reader` trait.
57 * There are three seek styles:
59 * 1. `SeekSet` means that the new position should become our position.
60 * 2. `SeekCur` means that we should seek from the current position.
61 * 3. `SeekEnd` means that we should seek from the end.
67 pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
71 * The core Reader trait. All readers must implement this trait.
78 // FIXME (#2004): Seekable really should be orthogonal.
80 // FIXME (#2982): This should probably return an error.
82 * Reads bytes and puts them into `bytes`. Returns the number of
85 * The number of bytes to be read is `len` or the end of the file,
86 * whichever comes first.
88 * The buffer must be at least `len` bytes long.
94 fn read(&self, bytes: &mut [u8], len: uint) -> uint;
97 * Reads a single byte.
99 * In the case of an EOF or an error, returns a negative value.
105 fn read_byte(&self) -> int;
108 * Returns a boolean value: are we currently at EOF?
114 fn eof(&self) -> bool;
117 * Seek to a given `position` in the stream.
119 * Takes an optional SeekStyle, which affects how we seek from the
120 * position. See `SeekStyle` docs for more details.
126 fn seek(&self, position: int, style: SeekStyle);
129 * Returns the current position within the stream.
135 fn tell(&self) -> uint;
138 impl Reader for @Reader {
139 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
140 self.read(bytes, len)
142 fn read_byte(&self) -> int {
145 fn eof(&self) -> bool {
148 fn seek(&self, position: int, style: SeekStyle) {
149 self.seek(position, style)
151 fn tell(&self) -> uint {
157 * The `ReaderUtil` trait is a home for many of the utility functions
158 * a particular Reader should implement.
160 * The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
161 * on higher-level concepts like 'chars' and 'lines.'
167 pub trait ReaderUtil {
170 * Reads `len` number of bytes, and gives you a new vector back.
176 fn read_bytes(&self, len: uint) -> ~[u8];
179 * Reads up until a specific byte is seen or EOF.
181 * The `include` parameter specifies if the character should be included
182 * in the returned string.
188 fn read_until(&self, c: u8, include: bool) -> ~str;
191 * Reads up until the first '\n' or EOF.
193 * The '\n' is not included in the result.
199 fn read_line(&self) -> ~str;
204 * Assumes that those chars are UTF-8 encoded.
206 * The '\n' is not included in the result.
212 fn read_chars(&self, n: uint) -> ~[char];
215 * Reads a single UTF-8 encoded char.
221 fn read_char(&self) -> char;
224 * Reads up until the first null byte or EOF.
226 * The null byte is not returned.
232 fn read_c_str(&self) -> ~str;
235 * Reads all remaining data in the stream.
241 fn read_whole_stream(&self) -> ~[u8];
244 * Iterate over every byte until EOF or the iterator breaks.
250 fn each_byte(&self, it: &fn(int) -> bool);
253 * Iterate over every char until EOF or the iterator breaks.
259 fn each_char(&self, it: &fn(char) -> bool);
262 * Iterate over every line until EOF or the iterator breaks.
268 fn each_line(&self, it: &fn(&str) -> bool);
271 * Reads all of the lines in the stream.
273 * Returns a vector of those lines.
279 fn read_lines(&self) -> ~[~str];
282 * Reads `n` little-endian unsigned integer bytes.
284 * `n` must be between 1 and 8, inclusive.
290 fn read_le_uint_n(&self, nbytes: uint) -> u64;
293 * Reads `n` little-endian signed integer bytes.
295 * `n` must be between 1 and 8, inclusive.
301 fn read_le_int_n(&self, nbytes: uint) -> i64;
304 * Reads `n` big-endian unsigned integer bytes.
306 * `n` must be between 1 and 8, inclusive.
312 fn read_be_uint_n(&self, nbytes: uint) -> u64;
315 * Reads `n` big-endian signed integer bytes.
317 * `n` must be between 1 and 8, inclusive.
323 fn read_be_int_n(&self, nbytes: uint) -> i64;
326 * Reads a little-endian unsigned integer.
328 * The number of bytes returned is system-dependant.
334 fn read_le_uint(&self) -> uint;
337 * Reads a little-endian integer.
339 * The number of bytes returned is system-dependant.
345 fn read_le_int(&self) -> int;
348 * Reads a big-endian unsigned integer.
350 * The number of bytes returned is system-dependant.
356 fn read_be_uint(&self) -> uint;
359 * Reads a big-endian integer.
361 * The number of bytes returned is system-dependant.
367 fn read_be_int(&self) -> int;
370 * Reads a big-endian `u64`.
372 * `u64`s are 8 bytes long.
378 fn read_be_u64(&self) -> u64;
381 * Reads a big-endian `u32`.
383 * `u32`s are 4 bytes long.
389 fn read_be_u32(&self) -> u32;
392 * Reads a big-endian `u16`.
394 * `u16`s are 2 bytes long.
400 fn read_be_u16(&self) -> u16;
403 * Reads a big-endian `i64`.
405 * `i64`s are 8 bytes long.
411 fn read_be_i64(&self) -> i64;
414 * Reads a big-endian `i32`.
416 * `i32`s are 4 bytes long.
422 fn read_be_i32(&self) -> i32;
425 * Reads a big-endian `i16`.
427 * `i16`s are 2 bytes long.
433 fn read_be_i16(&self) -> i16;
436 * Reads a big-endian `f64`.
438 * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
444 fn read_be_f64(&self) -> f64;
447 * Reads a big-endian `f32`.
449 * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
455 fn read_be_f32(&self) -> f32;
458 * Reads a little-endian `u64`.
460 * `u64`s are 8 bytes long.
466 fn read_le_u64(&self) -> u64;
469 * Reads a little-endian `u32`.
471 * `u32`s are 4 bytes long.
477 fn read_le_u32(&self) -> u32;
480 * Reads a little-endian `u16`.
482 * `u16`s are 2 bytes long.
488 fn read_le_u16(&self) -> u16;
491 * Reads a little-endian `i64`.
493 * `i64`s are 8 bytes long.
499 fn read_le_i64(&self) -> i64;
502 * Reads a little-endian `i32`.
504 * `i32`s are 4 bytes long.
510 fn read_le_i32(&self) -> i32;
513 * Reads a little-endian `i16`.
515 * `i16`s are 2 bytes long.
521 fn read_le_i16(&self) -> i16;
524 * Reads a little-endian `f64`.
526 * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
532 fn read_le_f64(&self) -> f64;
535 * Reads a little-endian `f32`.
537 * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
543 fn read_le_f32(&self) -> f32;
554 fn read_u8(&self) -> u8;
565 fn read_i8(&self) -> i8;
568 impl<T:Reader> ReaderUtil for T {
570 fn read_bytes(&self,len: uint) -> ~[u8] {
571 let mut bytes = vec::with_capacity(len);
572 unsafe { vec::raw::set_len(&mut bytes, len); }
574 let count = self.read(bytes, len);
576 unsafe { vec::raw::set_len(&mut bytes, count); }
580 fn read_until(&self, c: u8, include: bool) -> ~str {
583 let ch = self.read_byte();
584 if ch == -1 || ch == c as int {
585 if include && ch == c as int {
586 bytes.push(ch as u8);
590 bytes.push(ch as u8);
592 str::from_bytes(bytes)
595 fn read_line(&self) -> ~str {
596 self.read_until('\n' as u8, false)
599 fn read_chars(&self, n: uint) -> ~[char] {
600 // returns the (consumed offset, n_req), appends characters to &chars
601 fn chars_from_bytes<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
604 let bytes_len = bytes.len();
605 while i < bytes_len {
607 let w = str::utf8_char_width(b0);
612 chars.push(b0 as char);
615 // can't satisfy this char with the existing data
617 return (i - 1, end - bytes_len);
621 let next = bytes[i] as int;
623 assert!((next > -1));
624 assert!((next & 192 == 128));
626 val += (next & 63) as uint;
629 val += ((b0 << ((w + 1) as u8)) as uint)
630 << (w - 1) * 6 - w - 1u;
631 chars.push(val as char);
637 // might need more bytes, but reading n will never over-read
640 let data = self.read_bytes(nbread);
642 // eof - FIXME (#2004): should we do something if
643 // we're split in a unicode char?
646 bytes.push_all(data);
647 let (offset, nbreq) = chars_from_bytes::<T>(&bytes, &mut chars);
648 let ncreq = n - chars.len();
649 // again we either know we need a certain number of bytes
650 // to complete a character, or we make sure we don't
651 // over-read by reading 1-byte per char needed
652 nbread = if ncreq > nbreq { ncreq } else { nbreq };
654 bytes = vec::slice(bytes, offset, bytes.len()).to_vec();
660 fn read_char(&self) -> char {
661 let c = self.read_chars(1);
662 if vec::len(c) == 0 {
663 return -1 as char; // FIXME will this stay valid? // #2004
665 assert!((vec::len(c) == 1));
669 fn read_c_str(&self) -> ~str {
670 self.read_until(0u8, false)
673 fn read_whole_stream(&self) -> ~[u8] {
674 let mut bytes: ~[u8] = ~[];
675 while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
679 fn each_byte(&self, it: &fn(int) -> bool) {
681 if !it(self.read_byte()) { break; }
685 fn each_char(&self, it: &fn(char) -> bool) {
687 if !it(self.read_char()) { break; }
691 fn each_line(&self, it: &fn(s: &str) -> bool) {
693 // include the \n, so that we can distinguish an entirely empty
694 // line read after "...\n", and the trailing empty line in
696 let mut line = self.read_until('\n' as u8, true);
698 // blank line at the end of the reader is ignored
699 if self.eof() && line.is_empty() { break; }
701 // trim the \n, so that each_line is consistent with read_line
702 let n = str::len(line);
703 if line[n-1] == '\n' as u8 {
704 unsafe { str::raw::set_len(&mut line, n-1); }
707 if !it(line) { break; }
711 fn read_lines(&self) -> ~[~str] {
712 do vec::build |push| {
713 for self.each_line |line| {
714 push(str::from_slice(line));
719 // FIXME int reading methods need to deal with eof - issue #2004
721 fn read_le_uint_n(&self, nbytes: uint) -> u64 {
722 assert!(nbytes > 0 && nbytes <= 8);
724 let mut val = 0u64, pos = 0, i = nbytes;
726 val += (self.read_u8() as u64) << pos;
733 fn read_le_int_n(&self, nbytes: uint) -> i64 {
734 extend_sign(self.read_le_uint_n(nbytes), nbytes)
737 fn read_be_uint_n(&self, nbytes: uint) -> u64 {
738 assert!(nbytes > 0 && nbytes <= 8);
740 let mut val = 0u64, i = nbytes;
743 val += (self.read_u8() as u64) << i * 8;
748 fn read_be_int_n(&self, nbytes: uint) -> i64 {
749 extend_sign(self.read_be_uint_n(nbytes), nbytes)
752 fn read_le_uint(&self) -> uint {
753 self.read_le_uint_n(uint::bytes) as uint
756 fn read_le_int(&self) -> int {
757 self.read_le_int_n(int::bytes) as int
760 fn read_be_uint(&self) -> uint {
761 self.read_be_uint_n(uint::bytes) as uint
764 fn read_be_int(&self) -> int {
765 self.read_be_int_n(int::bytes) as int
768 fn read_be_u64(&self) -> u64 {
769 self.read_be_uint_n(8) as u64
772 fn read_be_u32(&self) -> u32 {
773 self.read_be_uint_n(4) as u32
776 fn read_be_u16(&self) -> u16 {
777 self.read_be_uint_n(2) as u16
780 fn read_be_i64(&self) -> i64 {
781 self.read_be_int_n(8) as i64
784 fn read_be_i32(&self) -> i32 {
785 self.read_be_int_n(4) as i32
788 fn read_be_i16(&self) -> i16 {
789 self.read_be_int_n(2) as i16
792 fn read_be_f64(&self) -> f64 {
794 cast::transmute::<u64, f64>(self.read_be_u64())
798 fn read_be_f32(&self) -> f32 {
800 cast::transmute::<u32, f32>(self.read_be_u32())
804 fn read_le_u64(&self) -> u64 {
805 self.read_le_uint_n(8) as u64
808 fn read_le_u32(&self) -> u32 {
809 self.read_le_uint_n(4) as u32
812 fn read_le_u16(&self) -> u16 {
813 self.read_le_uint_n(2) as u16
816 fn read_le_i64(&self) -> i64 {
817 self.read_le_int_n(8) as i64
820 fn read_le_i32(&self) -> i32 {
821 self.read_le_int_n(4) as i32
824 fn read_le_i16(&self) -> i16 {
825 self.read_le_int_n(2) as i16
828 fn read_le_f64(&self) -> f64 {
830 cast::transmute::<u64, f64>(self.read_le_u64())
834 fn read_le_f32(&self) -> f32 {
836 cast::transmute::<u32, f32>(self.read_le_u32())
840 fn read_u8(&self) -> u8 {
841 self.read_byte() as u8
844 fn read_i8(&self) -> i8 {
845 self.read_byte() as i8
849 fn extend_sign(val: u64, nbytes: uint) -> i64 {
850 let shift = (8 - nbytes) * 8;
851 (val << shift) as i64 >> shift
854 // Reader implementations
856 fn convert_whence(whence: SeekStyle) -> i32 {
857 return match whence {
864 impl Reader for *libc::FILE {
865 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
867 do vec::as_mut_buf(bytes) |buf_p, buf_len| {
868 assert!(buf_len >= len);
870 let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
871 len as size_t, *self);
877 fn read_byte(&self) -> int {
879 libc::fgetc(*self) as int
882 fn eof(&self) -> bool {
884 return libc::feof(*self) != 0 as c_int;
887 fn seek(&self, offset: int, whence: SeekStyle) {
889 assert!(libc::fseek(*self,
891 convert_whence(whence)) == 0 as c_int);
894 fn tell(&self) -> uint {
896 return libc::ftell(*self) as uint;
901 struct Wrapper<T, C> {
906 // A forwarding impl of reader that also holds on to a resource for the
907 // duration of its lifetime.
908 // FIXME there really should be a better way to do this // #2004
909 impl<R:Reader,C> Reader for Wrapper<R, C> {
910 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
911 self.base.read(bytes, len)
913 fn read_byte(&self) -> int { self.base.read_byte() }
914 fn eof(&self) -> bool { self.base.eof() }
915 fn seek(&self, off: int, whence: SeekStyle) {
916 self.base.seek(off, whence)
918 fn tell(&self) -> uint { self.base.tell() }
925 impl Drop for FILERes {
928 libc::fclose(self.f);
933 pub fn FILERes(f: *libc::FILE) -> FILERes {
939 pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
941 @Wrapper { base: f, cleanup: FILERes(f) } as @Reader
947 // FIXME (#2004): this should either be an trait-less impl, a set of
948 // top-level functions that take a reader, or a set of default methods on
949 // reader (which can then be called reader)
951 pub fn stdin() -> @Reader {
953 @rustrt::rust_get_stdin() as @Reader
957 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
959 let f = os::as_c_charp(path.to_str(), |pathbuf| {
960 os::as_c_charp("r", |modebuf|
961 libc::fopen(pathbuf, modebuf)
964 return if f as uint == 0u { result::Err(~"error opening "
967 result::Ok(FILE_reader(f, true))
974 pub struct BytesReader<'self> {
979 impl<'self> Reader for BytesReader<'self> {
980 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
981 let count = uint::min(len, self.bytes.len() - self.pos);
983 let view = vec::slice(self.bytes, self.pos, self.bytes.len());
984 vec::bytes::copy_memory(bytes, view, count);
990 fn read_byte(&self) -> int {
991 if self.pos == self.bytes.len() { return -1; }
992 let b = self.bytes[self.pos];
996 fn eof(&self) -> bool { self.pos == self.bytes.len() }
997 fn seek(&self, offset: int, whence: SeekStyle) {
999 self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
1001 fn tell(&self) -> uint { self.pos }
1004 pub fn with_bytes_reader<t>(bytes: &[u8], f: &fn(@Reader) -> t) -> t {
1005 f(@BytesReader { bytes: bytes, pos: 0u } as @Reader)
1008 pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
1009 str::byte_slice(s, |bytes| with_bytes_reader(bytes, f))
1013 pub enum FileFlag { Append, Create, Truncate, NoFlag, }
1015 // What type of writer are we?
1017 pub enum WriterType { Screen, File }
1019 // FIXME (#2004): Seekable really should be orthogonal.
1020 // FIXME (#2004): eventually u64
1021 /// The raw underlying writer trait. All writers must implement this.
1024 /// Write all of the given bytes.
1025 fn write(&self, v: &const [u8]);
1027 /// Move the current position within the stream. The second parameter
1028 /// determines the position that the first parameter is relative to.
1029 fn seek(&self, int, SeekStyle);
1031 /// Return the current position within the stream.
1032 fn tell(&self) -> uint;
1034 /// Flush the output buffer for this stream (if there is one).
1035 fn flush(&self) -> int;
1037 /// Determine if this Writer is writing to a file or not.
1038 fn get_type(&self) -> WriterType;
1041 impl Writer for @Writer {
1042 fn write(&self, v: &const [u8]) { self.write(v) }
1043 fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
1044 fn tell(&self) -> uint { self.tell() }
1045 fn flush(&self) -> int { self.flush() }
1046 fn get_type(&self) -> WriterType { self.get_type() }
1049 impl<W:Writer,C> Writer for Wrapper<W, C> {
1050 fn write(&self, bs: &const [u8]) { self.base.write(bs); }
1051 fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
1052 fn tell(&self) -> uint { self.base.tell() }
1053 fn flush(&self) -> int { self.base.flush() }
1054 fn get_type(&self) -> WriterType { File }
1057 impl Writer for *libc::FILE {
1058 fn write(&self, v: &const [u8]) {
1060 do vec::as_const_buf(v) |vbuf, len| {
1061 let nout = libc::fwrite(vbuf as *c_void,
1065 if nout != len as size_t {
1066 error!("error writing buffer");
1067 error!("%s", os::last_os_error());
1073 fn seek(&self, offset: int, whence: SeekStyle) {
1075 assert!(libc::fseek(*self,
1077 convert_whence(whence)) == 0 as c_int);
1080 fn tell(&self) -> uint {
1082 libc::ftell(*self) as uint
1085 fn flush(&self) -> int {
1087 libc::fflush(*self) as int
1090 fn get_type(&self) -> WriterType {
1092 let fd = libc::fileno(*self);
1093 if libc::isatty(fd) == 0 { File }
1099 pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
1101 @Wrapper { base: f, cleanup: FILERes(f) } as @Writer
1107 impl Writer for fd_t {
1108 fn write(&self, v: &const [u8]) {
1111 do vec::as_const_buf(v) |vbuf, len| {
1113 let vb = ptr::const_offset(vbuf, count) as *c_void;
1114 let nout = libc::write(*self, vb, len as size_t);
1115 if nout < 0 as ssize_t {
1116 error!("error writing buffer");
1117 error!("%s", os::last_os_error());
1120 count += nout as uint;
1125 fn seek(&self, _offset: int, _whence: SeekStyle) {
1126 error!("need 64-bit foreign calls for seek, sorry");
1129 fn tell(&self) -> uint {
1130 error!("need 64-bit foreign calls for tell, sorry");
1133 fn flush(&self) -> int { 0 }
1134 fn get_type(&self) -> WriterType {
1136 if libc::isatty(*self) == 0 { File } else { Screen }
1145 impl Drop for FdRes {
1146 fn finalize(&self) {
1148 libc::close(self.fd);
1153 pub fn FdRes(fd: fd_t) -> FdRes {
1159 pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
1161 @Wrapper { base: fd, cleanup: FdRes(fd) } as @Writer
1168 pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
1169 -> Result<@Writer, ~str> {
1172 (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
1176 fn wb() -> c_int { O_WRONLY as c_int }
1178 let mut fflags: c_int = wb();
1179 for vec::each(flags) |f| {
1181 Append => fflags |= O_APPEND as c_int,
1182 Create => fflags |= O_CREAT as c_int,
1183 Truncate => fflags |= O_TRUNC as c_int,
1188 do os::as_c_charp(path.to_str()) |pathbuf| {
1189 libc::open(pathbuf, fflags,
1190 (S_IRUSR | S_IWUSR) as c_int)
1193 if fd < (0 as c_int) {
1194 result::Err(fmt!("error opening %s: %s", path.to_str(),
1195 os::last_os_error()))
1197 result::Ok(fd_writer(fd, true))
1201 pub fn u64_to_le_bytes<T>(n: u64, size: uint,
1202 f: &fn(v: &[u8]) -> T) -> T {
1203 assert!(size <= 8u);
1205 1u => f(&[n as u8]),
1222 let mut bytes: ~[u8] = ~[], i = size, n = n;
1224 bytes.push((n & 255_u64) as u8);
1233 pub fn u64_to_be_bytes<T>(n: u64, size: uint,
1234 f: &fn(v: &[u8]) -> T) -> T {
1235 assert!(size <= 8u);
1237 1u => f(&[n as u8]),
1238 2u => f(&[(n >> 8) as u8,
1240 4u => f(&[(n >> 24) as u8,
1244 8u => f(&[(n >> 56) as u8,
1253 let mut bytes: ~[u8] = ~[];
1256 let shift = ((i - 1u) * 8u) as u64;
1257 bytes.push((n >> shift) as u8);
1265 pub fn u64_from_be_bytes(data: &const [u8],
1270 assert!((sz <= 8u));
1271 let mut val = 0_u64;
1272 let mut pos = start;
1275 val += (data[pos] as u64) << ((sz * 8u) as u64);
1281 // FIXME: #3048 combine trait+impl (or just move these to
1282 // default methods on writer)
1283 /// Generic utility functions defined on writers.
1284 pub trait WriterUtil {
1286 /// Write a single utf-8 encoded char.
1287 fn write_char(&self, ch: char);
1289 /// Write every char in the given str, encoded as utf-8.
1290 fn write_str(&self, s: &str);
1292 /// Write the given str, as utf-8, followed by '\n'.
1293 fn write_line(&self, s: &str);
1295 /// Write the result of passing n through `int::to_str_bytes`.
1296 fn write_int(&self, n: int);
1298 /// Write the result of passing n through `uint::to_str_bytes`.
1299 fn write_uint(&self, n: uint);
1301 /// Write a little-endian uint (number of bytes depends on system).
1302 fn write_le_uint(&self, n: uint);
1304 /// Write a little-endian int (number of bytes depends on system).
1305 fn write_le_int(&self, n: int);
1307 /// Write a big-endian uint (number of bytes depends on system).
1308 fn write_be_uint(&self, n: uint);
1310 /// Write a big-endian int (number of bytes depends on system).
1311 fn write_be_int(&self, n: int);
1313 /// Write a big-endian u64 (8 bytes).
1314 fn write_be_u64(&self, n: u64);
1316 /// Write a big-endian u32 (4 bytes).
1317 fn write_be_u32(&self, n: u32);
1319 /// Write a big-endian u16 (2 bytes).
1320 fn write_be_u16(&self, n: u16);
1322 /// Write a big-endian i64 (8 bytes).
1323 fn write_be_i64(&self, n: i64);
1325 /// Write a big-endian i32 (4 bytes).
1326 fn write_be_i32(&self, n: i32);
1328 /// Write a big-endian i16 (2 bytes).
1329 fn write_be_i16(&self, n: i16);
1331 /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
1332 fn write_be_f64(&self, f: f64);
1334 /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
1335 fn write_be_f32(&self, f: f32);
1337 /// Write a little-endian u64 (8 bytes).
1338 fn write_le_u64(&self, n: u64);
1340 /// Write a little-endian u32 (4 bytes).
1341 fn write_le_u32(&self, n: u32);
1343 /// Write a little-endian u16 (2 bytes).
1344 fn write_le_u16(&self, n: u16);
1346 /// Write a little-endian i64 (8 bytes).
1347 fn write_le_i64(&self, n: i64);
1349 /// Write a little-endian i32 (4 bytes).
1350 fn write_le_i32(&self, n: i32);
1352 /// Write a little-endian i16 (2 bytes).
1353 fn write_le_i16(&self, n: i16);
1355 /// Write a little-endian IEEE754 double-precision floating-point
1357 fn write_le_f64(&self, f: f64);
1359 /// Write a litten-endian IEEE754 single-precision floating-point
1361 fn write_le_f32(&self, f: f32);
1363 /// Write a u8 (1 byte).
1364 fn write_u8(&self, n: u8);
1366 /// Write a i8 (1 byte).
1367 fn write_i8(&self, n: i8);
1370 impl<T:Writer> WriterUtil for T {
1371 fn write_char(&self, ch: char) {
1372 if (ch as uint) < 128u {
1373 self.write(&[ch as u8]);
1375 self.write_str(str::from_char(ch));
1378 fn write_str(&self, s: &str) { str::byte_slice(s, |v| self.write(v)) }
1379 fn write_line(&self, s: &str) {
1381 self.write_str(&"\n");
1383 fn write_int(&self, n: int) {
1384 int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1386 fn write_uint(&self, n: uint) {
1387 uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1389 fn write_le_uint(&self, n: uint) {
1390 u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
1392 fn write_le_int(&self, n: int) {
1393 u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
1395 fn write_be_uint(&self, n: uint) {
1396 u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
1398 fn write_be_int(&self, n: int) {
1399 u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
1401 fn write_be_u64(&self, n: u64) {
1402 u64_to_be_bytes(n, 8u, |v| self.write(v))
1404 fn write_be_u32(&self, n: u32) {
1405 u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1407 fn write_be_u16(&self, n: u16) {
1408 u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1410 fn write_be_i64(&self, n: i64) {
1411 u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
1413 fn write_be_i32(&self, n: i32) {
1414 u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1416 fn write_be_i16(&self, n: i16) {
1417 u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1419 fn write_be_f64(&self, f:f64) {
1421 self.write_be_u64(cast::transmute(f))
1424 fn write_be_f32(&self, f:f32) {
1426 self.write_be_u32(cast::transmute(f))
1429 fn write_le_u64(&self, n: u64) {
1430 u64_to_le_bytes(n, 8u, |v| self.write(v))
1432 fn write_le_u32(&self, n: u32) {
1433 u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1435 fn write_le_u16(&self, n: u16) {
1436 u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1438 fn write_le_i64(&self, n: i64) {
1439 u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
1441 fn write_le_i32(&self, n: i32) {
1442 u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1444 fn write_le_i16(&self, n: i16) {
1445 u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1447 fn write_le_f64(&self, f:f64) {
1449 self.write_le_u64(cast::transmute(f))
1452 fn write_le_f32(&self, f:f32) {
1454 self.write_le_u32(cast::transmute(f))
1458 fn write_u8(&self, n: u8) { self.write([n]) }
1459 fn write_i8(&self, n: i8) { self.write([n as u8]) }
1463 #[allow(non_implicitly_copyable_typarams)]
1464 pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
1465 mk_file_writer(path, flags).chain(|w| result::Ok(w))
1469 // FIXME: fileflags // #2004
1470 pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
1472 let f = do os::as_c_charp(path.to_str()) |pathbuf| {
1473 do os::as_c_charp("w") |modebuf| {
1474 libc::fopen(pathbuf, modebuf)
1477 return if f as uint == 0u {
1478 result::Err(~"error opening " + path.to_str())
1480 result::Ok(FILE_writer(f, true))
1485 // FIXME (#2004) it would be great if this could be a const
1486 // FIXME (#2004) why are these different from the way stdin() is
1488 pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
1489 pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
1491 pub fn print(s: &str) { stdout().write_str(s); }
1492 pub fn println(s: &str) { stdout().write_line(s); }
1494 pub struct BytesWriter {
1499 impl Writer for BytesWriter {
1500 fn write(&self, v: &const [u8]) {
1501 let v_len = v.len();
1502 let bytes_len = vec::uniq_len(&const self.bytes);
1504 let count = uint::max(bytes_len, self.pos + v_len);
1505 vec::reserve(&mut self.bytes, count);
1508 vec::raw::set_len(&mut self.bytes, count);
1509 let view = vec::mut_slice(self.bytes, self.pos, count);
1510 vec::bytes::copy_memory(view, v, v_len);
1515 fn seek(&self, offset: int, whence: SeekStyle) {
1517 let len = vec::uniq_len(&const self.bytes);
1518 self.pos = seek_in_buf(offset, pos, len, whence);
1520 fn tell(&self) -> uint { self.pos }
1521 fn flush(&self) -> int { 0 }
1522 fn get_type(&self) -> WriterType { File }
1525 pub fn BytesWriter() -> BytesWriter {
1526 BytesWriter { bytes: ~[], mut pos: 0u }
1529 pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
1530 let wr = @BytesWriter();
1532 let @BytesWriter{bytes, _} = wr;
1536 pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
1537 let mut v = with_bytes_writer(f);
1539 // Make sure the vector has a trailing null and is proper utf8.
1541 assert!(str::is_utf8(v));
1543 unsafe { ::cast::transmute(v) }
1546 // Utility functions
1547 pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
1549 let mut bpos = pos as int;
1550 let blen = len as int;
1552 SeekSet => bpos = offset,
1553 SeekCur => bpos += offset,
1554 SeekEnd => bpos = blen + offset
1556 if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
1557 return bpos as uint;
1560 #[allow(non_implicitly_copyable_typarams)]
1561 pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
1562 result::chain(read_whole_file(file), |bytes| {
1563 if str::is_utf8(bytes) {
1564 result::Ok(str::from_bytes(bytes))
1566 result::Err(file.to_str() + ~" is not UTF-8")
1571 // FIXME (#2004): implement this in a low-level way. Going through the
1572 // abstractions is pointless.
1573 #[allow(non_implicitly_copyable_typarams)]
1574 pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
1575 result::chain(file_reader(file), |rdr| {
1576 result::Ok(rdr.read_whole_stream())
1583 use io::{FILERes, FdRes, fd_t};
1587 use option::{None, Option, Some};
1591 // whatever fsync does on that platform
1594 // fdatasync on linux, similiar or more on other platforms
1599 // You must additionally sync the parent directory as well!
1604 // Artifacts that need to fsync on destruction
1609 #[unsafe_destructor]
1610 impl<T:Copy> Drop for Res<T> {
1611 fn finalize(&self) {
1612 match self.arg.opt_level {
1615 // fail hard if not succesful
1616 assert!(((self.arg.fsync_fn)(self.arg.val, level)
1623 pub fn Res<t: Copy>(arg: Arg<t>) -> Res<t>{
1631 opt_level: Option<Level>,
1632 fsync_fn: @fn(f: t, Level) -> int,
1635 // fsync file after executing blk
1636 // FIXME (#2004) find better way to create resources within lifetime of
1638 pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
1639 blk: &fn(v: Res<*libc::FILE>)) {
1641 val: file.f, opt_level: opt_level,
1642 fsync_fn: |file, l| {
1644 os::fsync_fd(libc::fileno(file), l) as int
1650 // fsync fd after executing blk
1651 pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
1652 blk: &fn(v: Res<fd_t>)) {
1654 val: fd.fd, opt_level: opt_level,
1655 fsync_fn: |fd, l| os::fsync_fd(fd, l) as int
1659 // Type of objects that may want to fsync
1660 pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
1662 // Call o.fsync after executing blk
1663 pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
1664 blk: &fn(v: Res<@FSyncable>)) {
1666 val: o, opt_level: opt_level,
1667 fsync_fn: |o, l| o.fsync(l)
1675 use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
1685 let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
1688 ~"A hoopy frood who really knows where his towel is.";
1691 let out: @io::Writer =
1693 &io::file_writer(tmpfile, ~[io::Create, io::Truncate]));
1694 out.write_str(frood);
1696 let inp: @io::Reader = result::get(&io::file_reader(tmpfile));
1697 let frood2: ~str = inp.read_c_str();
1698 debug!(copy frood2);
1699 assert!(frood == frood2);
1703 fn test_readchars_empty() {
1704 do io::with_str_reader(~"") |inp| {
1705 let res : ~[char] = inp.read_chars(128);
1706 assert!((vec::len(res) == 0));
1711 fn test_read_line_utf8() {
1712 do io::with_str_reader(~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
1713 let line = inp.read_line();
1714 assert!(line == ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤");
1719 fn test_read_lines() {
1720 do io::with_str_reader(~"a\nb\nc\n") |inp| {
1721 assert!(inp.read_lines() == ~[~"a", ~"b", ~"c"]);
1724 do io::with_str_reader(~"a\nb\nc") |inp| {
1725 assert!(inp.read_lines() == ~[~"a", ~"b", ~"c"]);
1728 do io::with_str_reader(~"") |inp| {
1729 assert!(inp.read_lines().is_empty());
1734 fn test_readchars_wide() {
1735 let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
1736 let ivals : ~[int] = ~[
1737 29983, 38152, 30340, 27748,
1738 21273, 20999, 32905, 27748,
1739 104, 101, 108, 108, 111,
1740 29983, 38152, 30340, 27748,
1741 21273, 20999, 32905, 27748];
1742 fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
1743 do io::with_str_reader(s) |inp| {
1744 let res : ~[char] = inp.read_chars(len);
1745 if (len <= vec::len(ivals)) {
1746 assert!((vec::len(res) == len));
1748 assert!(vec::slice(ivals, 0u, vec::len(res)) ==
1749 vec::map(res, |x| *x as int));
1754 check_read_ln(i, wide_test, ivals);
1757 // check a long read for good measure
1758 check_read_ln(128, wide_test, ivals);
1762 fn test_readchar() {
1763 do io::with_str_reader(~"生") |inp| {
1764 let res : char = inp.read_char();
1765 assert!((res as int == 29983));
1770 fn test_readchar_empty() {
1771 do io::with_str_reader(~"") |inp| {
1772 let res : char = inp.read_char();
1773 assert!((res as int == -1));
1778 fn file_reader_not_exist() {
1779 match io::file_reader(&Path("not a file")) {
1780 result::Err(copy e) => {
1781 assert!(e == ~"error opening not a file");
1783 result::Ok(_) => fail!()
1789 #[ignore(cfg(windows))]
1790 fn test_read_buffer_too_small() {
1791 let path = &Path("tmp/lib-io-test-read-buffer-too-small.tmp");
1792 // ensure the file exists
1793 io::file_writer(path, [io::Create]).get();
1795 let file = io::file_reader(path).get();
1796 let mut buf = vec::from_elem(5, 0);
1797 file.read(buf, 6); // this should fail because buf is too small
1801 fn test_read_buffer_big_enough() {
1802 let path = &Path("tmp/lib-io-test-read-buffer-big-enough.tmp");
1803 // ensure the file exists
1804 io::file_writer(path, [io::Create]).get();
1806 let file = io::file_reader(path).get();
1807 let mut buf = vec::from_elem(5, 0);
1808 file.read(buf, 4); // this should succeed because buf is big enough
1812 fn test_write_empty() {
1813 let file = io::file_writer(&Path("tmp/lib-io-test-write-empty.tmp"),
1814 [io::Create]).get();
1819 fn file_writer_bad_name() {
1820 match io::file_writer(&Path("?/?"), ~[]) {
1821 result::Err(copy e) => {
1822 assert!(str::starts_with(e, "error opening"));
1824 result::Ok(_) => fail!()
1829 fn buffered_file_writer_bad_name() {
1830 match io::buffered_file_writer(&Path("?/?")) {
1831 result::Err(copy e) => {
1832 assert!(str::starts_with(e, "error opening"));
1834 result::Ok(_) => fail!()
1839 fn bytes_buffer_overwrite() {
1840 let wr = BytesWriter();
1841 wr.write(~[0u8, 1u8, 2u8, 3u8]);
1842 assert!(wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
1843 wr.seek(-2, SeekCur);
1844 wr.write(~[4u8, 5u8, 6u8, 7u8]);
1845 assert!(wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
1846 wr.seek(-2, SeekEnd);
1848 wr.seek(1, SeekSet);
1850 assert!(wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
1854 fn test_read_write_le() {
1855 let path = Path("tmp/lib-io-test-read-write-le.tmp");
1856 let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
1858 // write the ints to the file
1860 let file = io::file_writer(&path, [io::Create]).get();
1861 for uints.each |i| {
1862 file.write_le_u64(*i);
1866 // then read them back and check that they are the same
1868 let file = io::file_reader(&path).get();
1869 for uints.each |i| {
1870 assert!(file.read_le_u64() == *i);
1876 fn test_read_write_be() {
1877 let path = Path("tmp/lib-io-test-read-write-be.tmp");
1878 let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
1880 // write the ints to the file
1882 let file = io::file_writer(&path, [io::Create]).get();
1883 for uints.each |i| {
1884 file.write_be_u64(*i);
1888 // then read them back and check that they are the same
1890 let file = io::file_reader(&path).get();
1891 for uints.each |i| {
1892 assert!(file.read_be_u64() == *i);
1898 fn test_read_be_int_n() {
1899 let path = Path("tmp/lib-io-test-read-be-int-n.tmp");
1900 let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
1902 // write the ints to the file
1904 let file = io::file_writer(&path, [io::Create]).get();
1906 file.write_be_i32(*i);
1910 // then read them back and check that they are the same
1912 let file = io::file_reader(&path).get();
1914 // this tests that the sign extension is working
1915 // (comparing the values as i32 would not test this)
1916 assert!(file.read_be_int_n(4) == *i as i64);
1922 fn test_read_f32() {
1923 let path = Path("tmp/lib-io-test-read-f32.tmp");
1924 //big-endian floating-point 8.1250
1925 let buf = ~[0x41, 0x02, 0x00, 0x00];
1928 let file = io::file_writer(&path, [io::Create]).get();
1933 let file = io::file_reader(&path).get();
1934 let f = file.read_be_f32();
1935 assert!(f == 8.1250);
1940 fn test_read_write_f32() {
1941 let path = Path("tmp/lib-io-test-read-write-f32.tmp");
1945 let file = io::file_writer(&path, [io::Create]).get();
1946 file.write_be_f32(f);
1947 file.write_le_f32(f);
1951 let file = io::file_reader(&path).get();
1952 assert!(file.read_be_f32() == 8.1250);
1953 assert!(file.read_le_f32() == 8.1250);
1962 // indent-tabs-mode: nil
1963 // c-basic-offset: 4
1964 // buffer-file-coding-system: utf-8-unix