mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-03 17:35:28 +03:00
Remove std::io once and for all!
This commit is contained in:
+11
-9
@@ -97,6 +97,7 @@ pub mod reader {
|
||||
use std::cast::transmute;
|
||||
use std::int;
|
||||
use std::option::{None, Option, Some};
|
||||
use std::rt::io::extensions::u64_from_be_bytes;
|
||||
|
||||
// ebml reading
|
||||
|
||||
@@ -258,17 +259,17 @@ pub fn doc_as_u8(d: Doc) -> u8 {
|
||||
|
||||
pub fn doc_as_u16(d: Doc) -> u16 {
|
||||
assert_eq!(d.end, d.start + 2u);
|
||||
::std::io::u64_from_be_bytes(*d.data, d.start, 2u) as u16
|
||||
u64_from_be_bytes(*d.data, d.start, 2u) as u16
|
||||
}
|
||||
|
||||
pub fn doc_as_u32(d: Doc) -> u32 {
|
||||
assert_eq!(d.end, d.start + 4u);
|
||||
::std::io::u64_from_be_bytes(*d.data, d.start, 4u) as u32
|
||||
u64_from_be_bytes(*d.data, d.start, 4u) as u32
|
||||
}
|
||||
|
||||
pub fn doc_as_u64(d: Doc) -> u64 {
|
||||
assert_eq!(d.end, d.start + 8u);
|
||||
::std::io::u64_from_be_bytes(*d.data, d.start, 8u)
|
||||
u64_from_be_bytes(*d.data, d.start, 8u)
|
||||
}
|
||||
|
||||
pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
|
||||
@@ -610,6 +611,7 @@ pub mod writer {
|
||||
use std::rt::io;
|
||||
use std::rt::io::{Writer, Seek};
|
||||
use std::rt::io::mem::MemWriter;
|
||||
use std::rt::io::extensions::u64_to_be_bytes;
|
||||
|
||||
// ebml writing
|
||||
pub struct Encoder {
|
||||
@@ -693,19 +695,19 @@ pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
|
||||
}
|
||||
|
||||
pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
|
||||
do ::std::io::u64_to_be_bytes(v, 8u) |v| {
|
||||
do u64_to_be_bytes(v, 8u) |v| {
|
||||
self.wr_tagged_bytes(tag_id, v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
|
||||
do ::std::io::u64_to_be_bytes(v as u64, 4u) |v| {
|
||||
do u64_to_be_bytes(v as u64, 4u) |v| {
|
||||
self.wr_tagged_bytes(tag_id, v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
|
||||
do ::std::io::u64_to_be_bytes(v as u64, 2u) |v| {
|
||||
do u64_to_be_bytes(v as u64, 2u) |v| {
|
||||
self.wr_tagged_bytes(tag_id, v);
|
||||
}
|
||||
}
|
||||
@@ -715,19 +717,19 @@ pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
|
||||
}
|
||||
|
||||
pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
|
||||
do ::std::io::u64_to_be_bytes(v as u64, 8u) |v| {
|
||||
do u64_to_be_bytes(v as u64, 8u) |v| {
|
||||
self.wr_tagged_bytes(tag_id, v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
|
||||
do ::std::io::u64_to_be_bytes(v as u64, 4u) |v| {
|
||||
do u64_to_be_bytes(v as u64, 4u) |v| {
|
||||
self.wr_tagged_bytes(tag_id, v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
|
||||
do ::std::io::u64_to_be_bytes(v as u64, 2u) |v| {
|
||||
do u64_to_be_bytes(v as u64, 2u) |v| {
|
||||
self.wr_tagged_bytes(tag_id, v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
|
||||
|
||||
use std::{vec, str};
|
||||
use std::io::Reader;
|
||||
use std::hashmap::HashMap;
|
||||
use std::rt::io;
|
||||
use std::rt::io::extensions::{ReaderByteConversions, ReaderUtil};
|
||||
use super::super::TermInfo;
|
||||
|
||||
// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
|
||||
@@ -160,7 +161,8 @@
|
||||
"box1"];
|
||||
|
||||
/// Parse a compiled terminfo entry, using long capability names if `longnames` is true
|
||||
pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
|
||||
pub fn parse(mut file: &mut io::Reader,
|
||||
longnames: bool) -> Result<~TermInfo, ~str> {
|
||||
let bnames;
|
||||
let snames;
|
||||
let nnames;
|
||||
@@ -176,17 +178,17 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
|
||||
}
|
||||
|
||||
// Check magic number
|
||||
let magic = file.read_le_u16();
|
||||
let magic = file.read_le_u16_();
|
||||
if (magic != 0x011A) {
|
||||
return Err(format!("invalid magic number: expected {:x} but found {:x}",
|
||||
0x011A, magic as uint));
|
||||
}
|
||||
|
||||
let names_bytes = file.read_le_i16() as int;
|
||||
let bools_bytes = file.read_le_i16() as int;
|
||||
let numbers_count = file.read_le_i16() as int;
|
||||
let string_offsets_count = file.read_le_i16() as int;
|
||||
let string_table_bytes = file.read_le_i16() as int;
|
||||
let names_bytes = file.read_le_i16_() as int;
|
||||
let bools_bytes = file.read_le_i16_() as int;
|
||||
let numbers_count = file.read_le_i16_() as int;
|
||||
let string_offsets_count = file.read_le_i16_() as int;
|
||||
let string_table_bytes = file.read_le_i16_() as int;
|
||||
|
||||
assert!(names_bytes > 0);
|
||||
|
||||
@@ -224,7 +226,7 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
|
||||
let mut bools_map = HashMap::new();
|
||||
if bools_bytes != 0 {
|
||||
for i in range(0, bools_bytes) {
|
||||
let b = file.read_byte();
|
||||
let b = file.read_byte().unwrap();
|
||||
if b < 0 {
|
||||
error!("EOF reading bools after {} entries", i);
|
||||
return Err(~"error: expected more bools but hit EOF");
|
||||
@@ -245,7 +247,7 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
|
||||
let mut numbers_map = HashMap::new();
|
||||
if numbers_count != 0 {
|
||||
for i in range(0, numbers_count) {
|
||||
let n = file.read_le_u16();
|
||||
let n = file.read_le_u16_();
|
||||
if n != 0xFFFF {
|
||||
debug!("{}\\#{}", nnames[i], n);
|
||||
numbers_map.insert(nnames[i].to_owned(), n);
|
||||
@@ -260,7 +262,7 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> {
|
||||
if string_offsets_count != 0 {
|
||||
let mut string_offsets = vec::with_capacity(10);
|
||||
for _ in range(0, string_offsets_count) {
|
||||
string_offsets.push(file.read_le_u16());
|
||||
string_offsets.push(file.read_le_u16_());
|
||||
}
|
||||
|
||||
debug!("offsets: {:?}", string_offsets);
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
use std::{os, str};
|
||||
use std::os::getenv;
|
||||
use std::io::{file_reader, Reader};
|
||||
use std::rt::io;
|
||||
use std::rt::io::file::FileInfo;
|
||||
|
||||
/// Return path to database entry for `term`
|
||||
pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
|
||||
@@ -73,9 +74,9 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
|
||||
}
|
||||
|
||||
/// Return open file for `term`
|
||||
pub fn open(term: &str) -> Result<@Reader, ~str> {
|
||||
pub fn open(term: &str) -> Result<@mut io::Reader, ~str> {
|
||||
match get_dbpath_for_term(term) {
|
||||
Some(x) => file_reader(x),
|
||||
Some(x) => Ok(@mut x.open_reader(io::Open).unwrap() as @mut io::Reader),
|
||||
None => Err(format!("could not find terminfo entry for {}", term))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
use std::u64;
|
||||
use std::rt::io;
|
||||
use std::rt::io::extensions::u64_from_be_bytes;
|
||||
use std::option;
|
||||
use std::str;
|
||||
use std::vec;
|
||||
@@ -55,14 +56,14 @@ fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: u64) ->
|
||||
let index = reader::get_doc(d, tag_index);
|
||||
let table = reader::get_doc(index, tag_index_table);
|
||||
let hash_pos = table.start + (hash % 256 * 4) as uint;
|
||||
let pos = ::std::io::u64_from_be_bytes(*d.data, hash_pos, 4) as uint;
|
||||
let pos = u64_from_be_bytes(*d.data, hash_pos, 4) as uint;
|
||||
let tagged_doc = reader::doc_at(d.data, pos);
|
||||
|
||||
let belt = tag_index_buckets_bucket_elt;
|
||||
|
||||
let mut ret = None;
|
||||
do reader::tagged_docs(tagged_doc.doc, belt) |elt| {
|
||||
let pos = ::std::io::u64_from_be_bytes(*elt.data, elt.start, 4) as uint;
|
||||
let pos = u64_from_be_bytes(*elt.data, elt.start, 4) as uint;
|
||||
if eq_fn(elt.data.slice(elt.start + 4, elt.end)) {
|
||||
ret = Some(reader::doc_at(d.data, pos).doc);
|
||||
false
|
||||
@@ -77,7 +78,7 @@ fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: u64) ->
|
||||
|
||||
pub fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option<ebml::Doc> {
|
||||
fn eq_item(bytes: &[u8], item_id: int) -> bool {
|
||||
return ::std::io::u64_from_be_bytes(
|
||||
return u64_from_be_bytes(
|
||||
bytes.slice(0u, 4u), 0u, 4u) as int
|
||||
== item_id;
|
||||
}
|
||||
@@ -1253,7 +1254,7 @@ fn family_names_type(fam: Family) -> bool {
|
||||
|
||||
fn read_path(d: ebml::Doc) -> (~str, uint) {
|
||||
do reader::with_doc_data(d) |desc| {
|
||||
let pos = ::std::io::u64_from_be_bytes(desc, 0u, 4u) as uint;
|
||||
let pos = u64_from_be_bytes(desc, 0u, 4u) as uint;
|
||||
let pathbytes = desc.slice(4u, desc.len());
|
||||
let path = str::from_utf8(pathbytes);
|
||||
|
||||
|
||||
-1817
@@ -1,1817 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
|
||||
The `io` module contains basic input and output routines.
|
||||
|
||||
A quick summary:
|
||||
|
||||
## `Reader` and `Writer` traits
|
||||
|
||||
These traits define the minimal set of methods that anything that can do
|
||||
input and output should implement.
|
||||
|
||||
## `ReaderUtil` and `WriterUtil` traits
|
||||
|
||||
Richer methods that allow you to do more. `Reader` only lets you read a certain
|
||||
number of bytes into a buffer, while `ReaderUtil` allows you to read a whole
|
||||
line, for example.
|
||||
|
||||
Generally, these richer methods are probably the ones you want to actually
|
||||
use in day-to-day Rust.
|
||||
|
||||
Furthermore, because there is an implementation of `ReaderUtil` for
|
||||
`<T: Reader>`, when your input or output code implements `Reader`, you get
|
||||
all of these methods for free.
|
||||
|
||||
## `print` and `println`
|
||||
|
||||
These very useful functions are defined here. You generally don't need to
|
||||
import them, though, as the prelude already does.
|
||||
|
||||
## `stdin`, `stdout`, and `stderr`
|
||||
|
||||
These functions return references to the classic three file descriptors. They
|
||||
implement `Reader` and `Writer`, where appropriate.
|
||||
|
||||
*/
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use cast;
|
||||
use cast::transmute;
|
||||
use clone::Clone;
|
||||
use c_str::ToCStr;
|
||||
use container::Container;
|
||||
use int;
|
||||
use iter::Iterator;
|
||||
use libc::consts::os::posix88::*;
|
||||
use libc::{c_int, c_void, size_t};
|
||||
use libc;
|
||||
use num;
|
||||
use ops::Drop;
|
||||
use option::{Some, None};
|
||||
use os;
|
||||
use path::{Path,GenericPath};
|
||||
use ptr;
|
||||
use result::{Result, Ok, Err};
|
||||
use str::{StrSlice, OwnedStr};
|
||||
use str;
|
||||
use uint;
|
||||
use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
|
||||
use vec;
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub use rt::io::stdio::{print, println};
|
||||
|
||||
#[allow(non_camel_case_types)] // not sure what to do about this
|
||||
type fd_t = c_int;
|
||||
|
||||
mod rustrt {
|
||||
use libc;
|
||||
|
||||
#[link_name = "rustrt"]
|
||||
extern {
|
||||
pub fn rust_get_stdin() -> *libc::FILE;
|
||||
pub fn rust_get_stdout() -> *libc::FILE;
|
||||
pub fn rust_get_stderr() -> *libc::FILE;
|
||||
}
|
||||
}
|
||||
|
||||
// Reading
|
||||
|
||||
// FIXME (#2004): This is all buffered. We might need an unbuffered variant
|
||||
// as well
|
||||
/**
|
||||
* The SeekStyle enum describes the relationship between the position
|
||||
* we'd like to seek to from our current position. It's used as an argument
|
||||
* to the `seek` method defined on the `Reader` trait.
|
||||
*
|
||||
* There are three seek styles:
|
||||
*
|
||||
* 1. `SeekSet` means that the new position should become our position.
|
||||
* 2. `SeekCur` means that we should seek from the current position.
|
||||
* 3. `SeekEnd` means that we should seek from the end.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
|
||||
|
||||
|
||||
/**
|
||||
* The core Reader trait. All readers must implement this trait.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
pub trait Reader {
|
||||
// FIXME (#2004): Seekable really should be orthogonal.
|
||||
|
||||
// FIXME (#2982): This should probably return an error.
|
||||
/**
|
||||
* Reads bytes and puts them into `bytes`, advancing the cursor. Returns the
|
||||
* number of bytes read.
|
||||
*
|
||||
* The number of bytes to be read is `len` or the end of the file,
|
||||
* whichever comes first.
|
||||
*
|
||||
* The buffer must be at least `len` bytes long.
|
||||
*
|
||||
* `read` is conceptually similar to C's `fread` function.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
|
||||
|
||||
/**
|
||||
* Reads a single byte, advancing the cursor.
|
||||
*
|
||||
* In the case of an EOF or an error, returns a negative value.
|
||||
*
|
||||
* `read_byte` is conceptually similar to C's `getc` function.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_byte(&self) -> int;
|
||||
|
||||
/**
|
||||
* Returns a boolean value: are we currently at EOF?
|
||||
*
|
||||
* Note that stream position may be already at the end-of-file point,
|
||||
* but `eof` returns false until an attempt to read at that position.
|
||||
*
|
||||
* `eof` is conceptually similar to C's `feof` function.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn eof(&self) -> bool;
|
||||
|
||||
/**
|
||||
* Seek to a given `position` in the stream.
|
||||
*
|
||||
* Takes an optional SeekStyle, which affects how we seek from the
|
||||
* position. See `SeekStyle` docs for more details.
|
||||
*
|
||||
* `seek` is conceptually similar to C's `fseek` function.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn seek(&self, position: int, style: SeekStyle);
|
||||
|
||||
/**
|
||||
* Returns the current position within the stream.
|
||||
*
|
||||
* `tell` is conceptually similar to C's `ftell` function.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn tell(&self) -> uint;
|
||||
}
|
||||
|
||||
impl Reader for @Reader {
|
||||
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
||||
self.read(bytes, len)
|
||||
}
|
||||
fn read_byte(&self) -> int {
|
||||
self.read_byte()
|
||||
}
|
||||
fn eof(&self) -> bool {
|
||||
self.eof()
|
||||
}
|
||||
fn seek(&self, position: int, style: SeekStyle) {
|
||||
self.seek(position, style)
|
||||
}
|
||||
fn tell(&self) -> uint {
|
||||
self.tell()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ReaderUtil` trait is a home for many of the utility functions
|
||||
* a particular Reader should implement.
|
||||
*
|
||||
* The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
|
||||
* on higher-level concepts like 'chars' and 'lines.'
|
||||
*
|
||||
* # Examples:
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
pub trait ReaderUtil {
|
||||
|
||||
/**
|
||||
* Reads `len` number of bytes, and gives you a new vector back.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_bytes(&self, len: uint) -> ~[u8];
|
||||
|
||||
/**
|
||||
* Reads up until a specific byte is seen or EOF.
|
||||
*
|
||||
* The `include` parameter specifies if the character should be included
|
||||
* in the returned string.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_until(&self, c: u8, include: bool) -> ~str;
|
||||
|
||||
/**
|
||||
* Reads up until the first '\n' or EOF.
|
||||
*
|
||||
* The '\n' is not included in the result.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_line(&self) -> ~str;
|
||||
|
||||
/**
|
||||
* Reads `n` chars.
|
||||
*
|
||||
* Assumes that those chars are UTF-8 encoded.
|
||||
*
|
||||
* The '\n' is not included in the result.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_chars(&self, n: uint) -> ~[char];
|
||||
|
||||
/**
|
||||
* Reads a single UTF-8 encoded char.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_char(&self) -> char;
|
||||
|
||||
/**
|
||||
* Reads up until the first null byte or EOF.
|
||||
*
|
||||
* The null byte is not returned.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_c_str(&self) -> ~str;
|
||||
|
||||
/**
|
||||
* Reads all remaining data in the stream.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_whole_stream(&self) -> ~[u8];
|
||||
|
||||
/**
|
||||
* Iterate over every byte until EOF or the iterator breaks.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn each_byte(&self, it: &fn(int) -> bool) -> bool;
|
||||
|
||||
/**
|
||||
* Iterate over every char until EOF or the iterator breaks.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn each_char(&self, it: &fn(char) -> bool) -> bool;
|
||||
|
||||
/**
|
||||
* Iterate over every line until EOF or the iterator breaks.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn each_line(&self, it: &fn(&str) -> bool) -> bool;
|
||||
|
||||
/**
|
||||
* Reads all of the lines in the stream.
|
||||
*
|
||||
* Returns a vector of those lines.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_lines(&self) -> ~[~str];
|
||||
|
||||
/**
|
||||
* Reads `n` little-endian unsigned integer bytes.
|
||||
*
|
||||
* `n` must be between 1 and 8, inclusive.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_uint_n(&self, nbytes: uint) -> u64;
|
||||
|
||||
/**
|
||||
* Reads `n` little-endian signed integer bytes.
|
||||
*
|
||||
* `n` must be between 1 and 8, inclusive.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_int_n(&self, nbytes: uint) -> i64;
|
||||
|
||||
/**
|
||||
* Reads `n` big-endian unsigned integer bytes.
|
||||
*
|
||||
* `n` must be between 1 and 8, inclusive.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_uint_n(&self, nbytes: uint) -> u64;
|
||||
|
||||
/**
|
||||
* Reads `n` big-endian signed integer bytes.
|
||||
*
|
||||
* `n` must be between 1 and 8, inclusive.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_int_n(&self, nbytes: uint) -> i64;
|
||||
|
||||
/**
|
||||
* Reads a little-endian unsigned integer.
|
||||
*
|
||||
* The number of bytes returned is system-dependant.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_uint(&self) -> uint;
|
||||
|
||||
/**
|
||||
* Reads a little-endian integer.
|
||||
*
|
||||
* The number of bytes returned is system-dependant.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_int(&self) -> int;
|
||||
|
||||
/**
|
||||
* Reads a big-endian unsigned integer.
|
||||
*
|
||||
* The number of bytes returned is system-dependant.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_uint(&self) -> uint;
|
||||
|
||||
/**
|
||||
* Reads a big-endian integer.
|
||||
*
|
||||
* The number of bytes returned is system-dependant.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_int(&self) -> int;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `u64`.
|
||||
*
|
||||
* `u64`s are 8 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_u64(&self) -> u64;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `u32`.
|
||||
*
|
||||
* `u32`s are 4 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_u32(&self) -> u32;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `u16`.
|
||||
*
|
||||
* `u16`s are 2 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_u16(&self) -> u16;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `i64`.
|
||||
*
|
||||
* `i64`s are 8 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_i64(&self) -> i64;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `i32`.
|
||||
*
|
||||
* `i32`s are 4 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_i32(&self) -> i32;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `i16`.
|
||||
*
|
||||
* `i16`s are 2 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_i16(&self) -> i16;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `f64`.
|
||||
*
|
||||
* `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_f64(&self) -> f64;
|
||||
|
||||
/**
|
||||
* Reads a big-endian `f32`.
|
||||
*
|
||||
* `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_be_f32(&self) -> f32;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `u64`.
|
||||
*
|
||||
* `u64`s are 8 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_u64(&self) -> u64;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `u32`.
|
||||
*
|
||||
* `u32`s are 4 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_u32(&self) -> u32;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `u16`.
|
||||
*
|
||||
* `u16`s are 2 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_u16(&self) -> u16;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `i64`.
|
||||
*
|
||||
* `i64`s are 8 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_i64(&self) -> i64;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `i32`.
|
||||
*
|
||||
* `i32`s are 4 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_i32(&self) -> i32;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `i16`.
|
||||
*
|
||||
* `i16`s are 2 bytes long.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_i16(&self) -> i16;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `f64`.
|
||||
*
|
||||
* `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_f64(&self) -> f64;
|
||||
|
||||
/**
|
||||
* Reads a little-endian `f32`.
|
||||
*
|
||||
* `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_le_f32(&self) -> f32;
|
||||
|
||||
/**
|
||||
* Read a u8.
|
||||
*
|
||||
* `u8`s are 1 byte.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_u8(&self) -> u8;
|
||||
|
||||
/**
|
||||
* Read an i8.
|
||||
*
|
||||
* `i8`s are 1 byte.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* None right now.
|
||||
*/
|
||||
fn read_i8(&self) -> i8;
|
||||
}
|
||||
|
||||
impl<T:Reader> ReaderUtil for T {
|
||||
|
||||
fn read_bytes(&self, len: uint) -> ~[u8] {
|
||||
let mut bytes = vec::with_capacity(len);
|
||||
unsafe { vec::raw::set_len(&mut bytes, len); }
|
||||
|
||||
let count = self.read(bytes, len);
|
||||
|
||||
unsafe { vec::raw::set_len(&mut bytes, count); }
|
||||
bytes
|
||||
}
|
||||
|
||||
fn read_until(&self, c: u8, include: bool) -> ~str {
|
||||
let mut bytes = ~[];
|
||||
loop {
|
||||
let ch = self.read_byte();
|
||||
if ch == -1 || ch == c as int {
|
||||
if include && ch == c as int {
|
||||
bytes.push(ch as u8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
bytes.push(ch as u8);
|
||||
}
|
||||
str::from_utf8(bytes)
|
||||
}
|
||||
|
||||
fn read_line(&self) -> ~str {
|
||||
self.read_until('\n' as u8, false)
|
||||
}
|
||||
|
||||
fn read_chars(&self, n: uint) -> ~[char] {
|
||||
// returns the (consumed offset, n_req), appends characters to &chars
|
||||
fn chars_from_utf8<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
|
||||
-> (uint, uint) {
|
||||
let mut i = 0;
|
||||
let bytes_len = bytes.len();
|
||||
while i < bytes_len {
|
||||
let b0 = bytes[i];
|
||||
let w = str::utf8_char_width(b0);
|
||||
let end = i + w;
|
||||
i += 1;
|
||||
assert!((w > 0));
|
||||
if w == 1 {
|
||||
unsafe {
|
||||
chars.push(transmute(b0 as u32));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// can't satisfy this char with the existing data
|
||||
if end > bytes_len {
|
||||
return (i - 1, end - bytes_len);
|
||||
}
|
||||
let mut val = 0;
|
||||
while i < end {
|
||||
let next = bytes[i] as int;
|
||||
i += 1;
|
||||
assert!((next > -1));
|
||||
assert_eq!(next & 192, 128);
|
||||
val <<= 6;
|
||||
val += (next & 63) as uint;
|
||||
}
|
||||
// See str::StrSlice::char_at
|
||||
val += ((b0 << ((w + 1) as u8)) as uint)
|
||||
<< (w - 1) * 6 - w - 1u;
|
||||
unsafe {
|
||||
chars.push(transmute(val as u32));
|
||||
}
|
||||
}
|
||||
return (i, 0);
|
||||
}
|
||||
let mut bytes = ~[];
|
||||
let mut chars = ~[];
|
||||
// might need more bytes, but reading n will never over-read
|
||||
let mut nbread = n;
|
||||
while nbread > 0 {
|
||||
let data = self.read_bytes(nbread);
|
||||
if data.is_empty() {
|
||||
// eof - FIXME (#2004): should we do something if
|
||||
// we're split in a unicode char?
|
||||
break;
|
||||
}
|
||||
bytes.push_all(data);
|
||||
let (offset, nbreq) = chars_from_utf8::<T>(&bytes, &mut chars);
|
||||
let ncreq = n - chars.len();
|
||||
// again we either know we need a certain number of bytes
|
||||
// to complete a character, or we make sure we don't
|
||||
// over-read by reading 1-byte per char needed
|
||||
nbread = if ncreq > nbreq { ncreq } else { nbreq };
|
||||
if nbread > 0 {
|
||||
bytes = bytes.slice(offset, bytes.len()).to_owned();
|
||||
}
|
||||
}
|
||||
chars
|
||||
}
|
||||
|
||||
fn read_char(&self) -> char {
|
||||
let c = self.read_chars(1);
|
||||
if c.len() == 0 {
|
||||
return unsafe { transmute(-1u32) }; // FIXME: #8971: unsound
|
||||
}
|
||||
assert_eq!(c.len(), 1);
|
||||
return c[0];
|
||||
}
|
||||
|
||||
fn read_c_str(&self) -> ~str {
|
||||
self.read_until(0u8, false)
|
||||
}
|
||||
|
||||
fn read_whole_stream(&self) -> ~[u8] {
|
||||
let mut bytes: ~[u8] = ~[];
|
||||
while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
|
||||
bytes
|
||||
}
|
||||
|
||||
fn each_byte(&self, it: &fn(int) -> bool) -> bool {
|
||||
loop {
|
||||
match self.read_byte() {
|
||||
-1 => break,
|
||||
ch => if !it(ch) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn each_char(&self, it: &fn(char) -> bool) -> bool {
|
||||
// FIXME: #8971: unsound
|
||||
let eof: char = unsafe { transmute(-1u32) };
|
||||
loop {
|
||||
match self.read_char() {
|
||||
c if c == eof => break,
|
||||
ch => if !it(ch) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn each_line(&self, it: &fn(s: &str) -> bool) -> bool {
|
||||
while !self.eof() {
|
||||
// include the \n, so that we can distinguish an entirely empty
|
||||
// line read after "...\n", and the trailing empty line in
|
||||
// "...\n\n".
|
||||
let mut line = self.read_until('\n' as u8, true);
|
||||
|
||||
// blank line at the end of the reader is ignored
|
||||
if self.eof() && line.is_empty() { break; }
|
||||
|
||||
// trim the \n, so that each_line is consistent with read_line
|
||||
let n = line.len();
|
||||
if line[n-1] == '\n' as u8 {
|
||||
unsafe { str::raw::set_len(&mut line, n-1); }
|
||||
}
|
||||
|
||||
if !it(line) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn read_lines(&self) -> ~[~str] {
|
||||
do vec::build(None) |push| {
|
||||
do self.each_line |line| {
|
||||
push(line.to_owned());
|
||||
true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME int reading methods need to deal with eof - issue #2004
|
||||
|
||||
fn read_le_uint_n(&self, nbytes: uint) -> u64 {
|
||||
assert!(nbytes > 0 && nbytes <= 8);
|
||||
|
||||
let mut val = 0u64;
|
||||
let mut pos = 0;
|
||||
let mut i = nbytes;
|
||||
while i > 0 {
|
||||
val += (self.read_u8() as u64) << pos;
|
||||
pos += 8;
|
||||
i -= 1;
|
||||
}
|
||||
val
|
||||
}
|
||||
|
||||
fn read_le_int_n(&self, nbytes: uint) -> i64 {
|
||||
extend_sign(self.read_le_uint_n(nbytes), nbytes)
|
||||
}
|
||||
|
||||
fn read_be_uint_n(&self, nbytes: uint) -> u64 {
|
||||
assert!(nbytes > 0 && nbytes <= 8);
|
||||
|
||||
let mut val = 0u64;
|
||||
let mut i = nbytes;
|
||||
while i > 0 {
|
||||
i -= 1;
|
||||
val += (self.read_u8() as u64) << i * 8;
|
||||
}
|
||||
val
|
||||
}
|
||||
|
||||
fn read_be_int_n(&self, nbytes: uint) -> i64 {
|
||||
extend_sign(self.read_be_uint_n(nbytes), nbytes)
|
||||
}
|
||||
|
||||
fn read_le_uint(&self) -> uint {
|
||||
self.read_le_uint_n(uint::bytes) as uint
|
||||
}
|
||||
|
||||
fn read_le_int(&self) -> int {
|
||||
self.read_le_int_n(int::bytes) as int
|
||||
}
|
||||
|
||||
fn read_be_uint(&self) -> uint {
|
||||
self.read_be_uint_n(uint::bytes) as uint
|
||||
}
|
||||
|
||||
fn read_be_int(&self) -> int {
|
||||
self.read_be_int_n(int::bytes) as int
|
||||
}
|
||||
|
||||
fn read_be_u64(&self) -> u64 {
|
||||
self.read_be_uint_n(8) as u64
|
||||
}
|
||||
|
||||
fn read_be_u32(&self) -> u32 {
|
||||
self.read_be_uint_n(4) as u32
|
||||
}
|
||||
|
||||
fn read_be_u16(&self) -> u16 {
|
||||
self.read_be_uint_n(2) as u16
|
||||
}
|
||||
|
||||
fn read_be_i64(&self) -> i64 {
|
||||
self.read_be_int_n(8) as i64
|
||||
}
|
||||
|
||||
fn read_be_i32(&self) -> i32 {
|
||||
self.read_be_int_n(4) as i32
|
||||
}
|
||||
|
||||
fn read_be_i16(&self) -> i16 {
|
||||
self.read_be_int_n(2) as i16
|
||||
}
|
||||
|
||||
fn read_be_f64(&self) -> f64 {
|
||||
unsafe {
|
||||
cast::transmute::<u64, f64>(self.read_be_u64())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_be_f32(&self) -> f32 {
|
||||
unsafe {
|
||||
cast::transmute::<u32, f32>(self.read_be_u32())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_le_u64(&self) -> u64 {
|
||||
self.read_le_uint_n(8) as u64
|
||||
}
|
||||
|
||||
fn read_le_u32(&self) -> u32 {
|
||||
self.read_le_uint_n(4) as u32
|
||||
}
|
||||
|
||||
fn read_le_u16(&self) -> u16 {
|
||||
self.read_le_uint_n(2) as u16
|
||||
}
|
||||
|
||||
fn read_le_i64(&self) -> i64 {
|
||||
self.read_le_int_n(8) as i64
|
||||
}
|
||||
|
||||
fn read_le_i32(&self) -> i32 {
|
||||
self.read_le_int_n(4) as i32
|
||||
}
|
||||
|
||||
fn read_le_i16(&self) -> i16 {
|
||||
self.read_le_int_n(2) as i16
|
||||
}
|
||||
|
||||
fn read_le_f64(&self) -> f64 {
|
||||
unsafe {
|
||||
cast::transmute::<u64, f64>(self.read_le_u64())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_le_f32(&self) -> f32 {
|
||||
unsafe {
|
||||
cast::transmute::<u32, f32>(self.read_le_u32())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_u8(&self) -> u8 {
|
||||
self.read_byte() as u8
|
||||
}
|
||||
|
||||
fn read_i8(&self) -> i8 {
|
||||
self.read_byte() as i8
|
||||
}
|
||||
}
|
||||
|
||||
fn extend_sign(val: u64, nbytes: uint) -> i64 {
|
||||
let shift = (8 - nbytes) * 8;
|
||||
(val << shift) as i64 >> shift
|
||||
}
|
||||
|
||||
// Reader implementations
|
||||
|
||||
fn convert_whence(whence: SeekStyle) -> i32 {
|
||||
return match whence {
|
||||
SeekSet => 0i32,
|
||||
SeekCur => 1i32,
|
||||
SeekEnd => 2i32
|
||||
};
|
||||
}
|
||||
|
||||
impl Reader for *libc::FILE {
|
||||
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
do bytes.as_mut_buf |buf_p, buf_len| {
|
||||
assert!(buf_len >= len);
|
||||
|
||||
let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
|
||||
len as size_t, *self) as uint;
|
||||
if count < len {
|
||||
match libc::ferror(*self) {
|
||||
0 => (),
|
||||
_ => {
|
||||
error!("error reading buffer: {}", os::last_os_error());
|
||||
fail!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
fn read_byte(&self) -> int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
libc::fgetc(*self) as int
|
||||
}
|
||||
}
|
||||
fn eof(&self) -> bool {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
return libc::feof(*self) != 0 as c_int;
|
||||
}
|
||||
}
|
||||
fn seek(&self, offset: int, whence: SeekStyle) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
assert!(libc::fseek(*self,
|
||||
offset as libc::c_long,
|
||||
convert_whence(whence)) == 0 as c_int);
|
||||
}
|
||||
}
|
||||
fn tell(&self) -> uint {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
return libc::ftell(*self) as uint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Wrapper<T, C> {
|
||||
base: T,
|
||||
cleanup: C,
|
||||
}
|
||||
|
||||
// A forwarding impl of reader that also holds on to a resource for the
|
||||
// duration of its lifetime.
|
||||
// FIXME there really should be a better way to do this // #2004
|
||||
impl<R:Reader,C> Reader for Wrapper<R, C> {
|
||||
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
||||
self.base.read(bytes, len)
|
||||
}
|
||||
fn read_byte(&self) -> int { self.base.read_byte() }
|
||||
fn eof(&self) -> bool { self.base.eof() }
|
||||
fn seek(&self, off: int, whence: SeekStyle) {
|
||||
self.base.seek(off, whence)
|
||||
}
|
||||
fn tell(&self) -> uint { self.base.tell() }
|
||||
}
|
||||
|
||||
pub struct FILERes {
|
||||
priv f: *libc::FILE,
|
||||
}
|
||||
|
||||
impl FILERes {
|
||||
fn new(f: *libc::FILE) -> FILERes {
|
||||
FILERes { f: f }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FILERes {
|
||||
fn drop(&mut self) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
libc::fclose(self.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
let f = do path.with_c_str |pathbuf| {
|
||||
do "rb".with_c_str |modebuf| {
|
||||
unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
|
||||
}
|
||||
};
|
||||
|
||||
if f as uint == 0u {
|
||||
do path.display().with_str |p| {
|
||||
Err(~"error opening " + p)
|
||||
}
|
||||
} else {
|
||||
Ok(@Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader)
|
||||
}
|
||||
}
|
||||
|
||||
// Writing
|
||||
pub enum FileFlag { Append, Create, Truncate, NoFlag, }
|
||||
|
||||
// What type of writer are we?
|
||||
#[deriving(Eq)]
|
||||
pub enum WriterType { Screen, File }
|
||||
|
||||
// FIXME (#2004): Seekable really should be orthogonal.
|
||||
// FIXME (#2004): eventually u64
|
||||
/// The raw underlying writer trait. All writers must implement this.
|
||||
pub trait Writer {
|
||||
|
||||
/// Write all of the given bytes.
|
||||
fn write(&self, v: &[u8]);
|
||||
|
||||
/// Move the current position within the stream. The second parameter
|
||||
/// determines the position that the first parameter is relative to.
|
||||
fn seek(&self, int, SeekStyle);
|
||||
|
||||
/// Return the current position within the stream.
|
||||
fn tell(&self) -> uint;
|
||||
|
||||
/// Flush the output buffer for this stream (if there is one).
|
||||
fn flush(&self) -> int;
|
||||
|
||||
/// Determine if this Writer is writing to a file or not.
|
||||
fn get_type(&self) -> WriterType;
|
||||
}
|
||||
|
||||
impl Writer for @Writer {
|
||||
fn write(&self, v: &[u8]) { self.write(v) }
|
||||
fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
|
||||
fn tell(&self) -> uint { self.tell() }
|
||||
fn flush(&self) -> int { self.flush() }
|
||||
fn get_type(&self) -> WriterType { self.get_type() }
|
||||
}
|
||||
|
||||
impl<W:Writer,C> Writer for Wrapper<W, C> {
|
||||
fn write(&self, bs: &[u8]) { self.base.write(bs); }
|
||||
fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
|
||||
fn tell(&self) -> uint { self.base.tell() }
|
||||
fn flush(&self) -> int { self.base.flush() }
|
||||
fn get_type(&self) -> WriterType { File }
|
||||
}
|
||||
|
||||
impl Writer for *libc::FILE {
|
||||
fn write(&self, v: &[u8]) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
do v.as_imm_buf |vbuf, len| {
|
||||
let nout = libc::fwrite(vbuf as *c_void,
|
||||
1,
|
||||
len as size_t,
|
||||
*self);
|
||||
if nout != len as size_t {
|
||||
error!("error writing buffer: {}", os::last_os_error());
|
||||
fail!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn seek(&self, offset: int, whence: SeekStyle) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
assert!(libc::fseek(*self,
|
||||
offset as libc::c_long,
|
||||
convert_whence(whence)) == 0 as c_int);
|
||||
}
|
||||
}
|
||||
fn tell(&self) -> uint {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
libc::ftell(*self) as uint
|
||||
}
|
||||
}
|
||||
fn flush(&self) -> int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
libc::fflush(*self) as int
|
||||
}
|
||||
}
|
||||
fn get_type(&self) -> WriterType {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
let fd = libc::fileno(*self);
|
||||
if libc::isatty(fd) == 0 { File }
|
||||
else { Screen }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for fd_t {
|
||||
fn write(&self, v: &[u8]) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
#[cfg(windows)]
|
||||
type IoSize = libc::c_uint;
|
||||
#[cfg(windows)]
|
||||
type IoRet = c_int;
|
||||
|
||||
#[cfg(unix)]
|
||||
type IoSize = size_t;
|
||||
#[cfg(unix)]
|
||||
type IoRet = libc::ssize_t;
|
||||
|
||||
unsafe {
|
||||
let mut count = 0u;
|
||||
do v.as_imm_buf |vbuf, len| {
|
||||
while count < len {
|
||||
let vb = ptr::offset(vbuf, count as int) as *c_void;
|
||||
let nout = libc::write(*self, vb, len as IoSize);
|
||||
if nout < 0 as IoRet {
|
||||
error!("error writing buffer: {}", os::last_os_error());
|
||||
fail!();
|
||||
}
|
||||
count += nout as uint;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn seek(&self, _offset: int, _whence: SeekStyle) {
|
||||
error!("need 64-bit foreign calls for seek, sorry");
|
||||
fail!();
|
||||
}
|
||||
fn tell(&self) -> uint {
|
||||
error!("need 64-bit foreign calls for tell, sorry");
|
||||
fail!();
|
||||
}
|
||||
fn flush(&self) -> int { 0 }
|
||||
fn get_type(&self) -> WriterType {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
if libc::isatty(*self) == 0 { File } else { Screen }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FdRes {
|
||||
priv fd: fd_t,
|
||||
}
|
||||
|
||||
impl FdRes {
|
||||
fn new(fd: fd_t) -> FdRes {
|
||||
FdRes { fd: fd }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FdRes {
|
||||
fn drop(&mut self) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
unsafe {
|
||||
libc::close(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
|
||||
-> Result<@Writer, ~str> {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
#[cfg(windows)]
|
||||
fn wb() -> c_int {
|
||||
(O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn wb() -> c_int { O_WRONLY as c_int }
|
||||
|
||||
let mut fflags: c_int = wb();
|
||||
for f in flags.iter() {
|
||||
match *f {
|
||||
Append => fflags |= O_APPEND as c_int,
|
||||
Create => fflags |= O_CREAT as c_int,
|
||||
Truncate => fflags |= O_TRUNC as c_int,
|
||||
NoFlag => ()
|
||||
}
|
||||
}
|
||||
let fd = unsafe {
|
||||
do path.with_c_str |pathbuf| {
|
||||
libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int)
|
||||
}
|
||||
};
|
||||
if fd < (0 as c_int) {
|
||||
Err(format!("error opening {}: {}", path.display(), os::last_os_error()))
|
||||
} else {
|
||||
Ok(@Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_to_le_bytes<T>(n: u64, size: uint,
|
||||
f: &fn(v: &[u8]) -> T) -> T {
|
||||
assert!(size <= 8u);
|
||||
match size {
|
||||
1u => f(&[n as u8]),
|
||||
2u => f(&[n as u8,
|
||||
(n >> 8) as u8]),
|
||||
4u => f(&[n as u8,
|
||||
(n >> 8) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 24) as u8]),
|
||||
8u => f(&[n as u8,
|
||||
(n >> 8) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 24) as u8,
|
||||
(n >> 32) as u8,
|
||||
(n >> 40) as u8,
|
||||
(n >> 48) as u8,
|
||||
(n >> 56) as u8]),
|
||||
_ => {
|
||||
|
||||
let mut bytes: ~[u8] = ~[];
|
||||
let mut i = size;
|
||||
let mut n = n;
|
||||
while i > 0u {
|
||||
bytes.push((n & 255_u64) as u8);
|
||||
n >>= 8_u64;
|
||||
i -= 1u;
|
||||
}
|
||||
f(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_to_be_bytes<T>(n: u64, size: uint,
|
||||
f: &fn(v: &[u8]) -> T) -> T {
|
||||
assert!(size <= 8u);
|
||||
match size {
|
||||
1u => f(&[n as u8]),
|
||||
2u => f(&[(n >> 8) as u8,
|
||||
n as u8]),
|
||||
4u => f(&[(n >> 24) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 8) as u8,
|
||||
n as u8]),
|
||||
8u => f(&[(n >> 56) as u8,
|
||||
(n >> 48) as u8,
|
||||
(n >> 40) as u8,
|
||||
(n >> 32) as u8,
|
||||
(n >> 24) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 8) as u8,
|
||||
n as u8]),
|
||||
_ => {
|
||||
let mut bytes: ~[u8] = ~[];
|
||||
let mut i = size;
|
||||
while i > 0u {
|
||||
let shift = ((i - 1u) * 8u) as u64;
|
||||
bytes.push((n >> shift) as u8);
|
||||
i -= 1u;
|
||||
}
|
||||
f(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_from_be_bytes(data: &[u8],
|
||||
start: uint,
|
||||
size: uint)
|
||||
-> u64 {
|
||||
let mut sz = size;
|
||||
assert!((sz <= 8u));
|
||||
let mut val = 0_u64;
|
||||
let mut pos = start;
|
||||
while sz > 0u {
|
||||
sz -= 1u;
|
||||
val += (data[pos] as u64) << ((sz * 8u) as u64);
|
||||
pos += 1u;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// FIXME: #3048 combine trait+impl (or just move these to
|
||||
// default methods on writer)
|
||||
/// Generic utility functions defined on writers.
|
||||
pub trait WriterUtil {
|
||||
|
||||
/// Write a single utf-8 encoded char.
|
||||
fn write_char(&self, ch: char);
|
||||
|
||||
/// Write every char in the given str, encoded as utf-8.
|
||||
fn write_str(&self, s: &str);
|
||||
|
||||
/// Write the given str, as utf-8, followed by '\n'.
|
||||
fn write_line(&self, s: &str);
|
||||
|
||||
/// Write the result of passing n through `int::to_str_bytes`.
|
||||
fn write_int(&self, n: int);
|
||||
|
||||
/// Write the result of passing n through `uint::to_str_bytes`.
|
||||
fn write_uint(&self, n: uint);
|
||||
|
||||
/// Write a little-endian uint (number of bytes depends on system).
|
||||
fn write_le_uint(&self, n: uint);
|
||||
|
||||
/// Write a little-endian int (number of bytes depends on system).
|
||||
fn write_le_int(&self, n: int);
|
||||
|
||||
/// Write a big-endian uint (number of bytes depends on system).
|
||||
fn write_be_uint(&self, n: uint);
|
||||
|
||||
/// Write a big-endian int (number of bytes depends on system).
|
||||
fn write_be_int(&self, n: int);
|
||||
|
||||
/// Write a big-endian u64 (8 bytes).
|
||||
fn write_be_u64(&self, n: u64);
|
||||
|
||||
/// Write a big-endian u32 (4 bytes).
|
||||
fn write_be_u32(&self, n: u32);
|
||||
|
||||
/// Write a big-endian u16 (2 bytes).
|
||||
fn write_be_u16(&self, n: u16);
|
||||
|
||||
/// Write a big-endian i64 (8 bytes).
|
||||
fn write_be_i64(&self, n: i64);
|
||||
|
||||
/// Write a big-endian i32 (4 bytes).
|
||||
fn write_be_i32(&self, n: i32);
|
||||
|
||||
/// Write a big-endian i16 (2 bytes).
|
||||
fn write_be_i16(&self, n: i16);
|
||||
|
||||
/// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
|
||||
fn write_be_f64(&self, f: f64);
|
||||
|
||||
/// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
|
||||
fn write_be_f32(&self, f: f32);
|
||||
|
||||
/// Write a little-endian u64 (8 bytes).
|
||||
fn write_le_u64(&self, n: u64);
|
||||
|
||||
/// Write a little-endian u32 (4 bytes).
|
||||
fn write_le_u32(&self, n: u32);
|
||||
|
||||
/// Write a little-endian u16 (2 bytes).
|
||||
fn write_le_u16(&self, n: u16);
|
||||
|
||||
/// Write a little-endian i64 (8 bytes).
|
||||
fn write_le_i64(&self, n: i64);
|
||||
|
||||
/// Write a little-endian i32 (4 bytes).
|
||||
fn write_le_i32(&self, n: i32);
|
||||
|
||||
/// Write a little-endian i16 (2 bytes).
|
||||
fn write_le_i16(&self, n: i16);
|
||||
|
||||
/// Write a little-endian IEEE754 double-precision floating-point
|
||||
/// (8 bytes).
|
||||
fn write_le_f64(&self, f: f64);
|
||||
|
||||
/// Write a little-endian IEEE754 single-precision floating-point
|
||||
/// (4 bytes).
|
||||
fn write_le_f32(&self, f: f32);
|
||||
|
||||
/// Write a u8 (1 byte).
|
||||
fn write_u8(&self, n: u8);
|
||||
|
||||
/// Write a i8 (1 byte).
|
||||
fn write_i8(&self, n: i8);
|
||||
}
|
||||
|
||||
impl<T:Writer> WriterUtil for T {
|
||||
fn write_char(&self, ch: char) {
|
||||
if (ch as uint) < 128u {
|
||||
self.write(&[ch as u8]);
|
||||
} else {
|
||||
self.write_str(str::from_char(ch));
|
||||
}
|
||||
}
|
||||
fn write_str(&self, s: &str) { self.write(s.as_bytes()) }
|
||||
fn write_line(&self, s: &str) {
|
||||
self.write_str(s);
|
||||
self.write_str(&"\n");
|
||||
}
|
||||
fn write_int(&self, n: int) {
|
||||
int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
|
||||
}
|
||||
fn write_uint(&self, n: uint) {
|
||||
uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
|
||||
}
|
||||
fn write_le_uint(&self, n: uint) {
|
||||
u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
|
||||
}
|
||||
fn write_le_int(&self, n: int) {
|
||||
u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
|
||||
}
|
||||
fn write_be_uint(&self, n: uint) {
|
||||
u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
|
||||
}
|
||||
fn write_be_int(&self, n: int) {
|
||||
u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
|
||||
}
|
||||
fn write_be_u64(&self, n: u64) {
|
||||
u64_to_be_bytes(n, 8u, |v| self.write(v))
|
||||
}
|
||||
fn write_be_u32(&self, n: u32) {
|
||||
u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
fn write_be_u16(&self, n: u16) {
|
||||
u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
fn write_be_i64(&self, n: i64) {
|
||||
u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
|
||||
}
|
||||
fn write_be_i32(&self, n: i32) {
|
||||
u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
fn write_be_i16(&self, n: i16) {
|
||||
u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
fn write_be_f64(&self, f:f64) {
|
||||
unsafe {
|
||||
self.write_be_u64(cast::transmute(f))
|
||||
}
|
||||
}
|
||||
fn write_be_f32(&self, f:f32) {
|
||||
unsafe {
|
||||
self.write_be_u32(cast::transmute(f))
|
||||
}
|
||||
}
|
||||
fn write_le_u64(&self, n: u64) {
|
||||
u64_to_le_bytes(n, 8u, |v| self.write(v))
|
||||
}
|
||||
fn write_le_u32(&self, n: u32) {
|
||||
u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
fn write_le_u16(&self, n: u16) {
|
||||
u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
fn write_le_i64(&self, n: i64) {
|
||||
u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
|
||||
}
|
||||
fn write_le_i32(&self, n: i32) {
|
||||
u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
||||
}
|
||||
fn write_le_i16(&self, n: i16) {
|
||||
u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
||||
}
|
||||
fn write_le_f64(&self, f:f64) {
|
||||
unsafe {
|
||||
self.write_le_u64(cast::transmute(f))
|
||||
}
|
||||
}
|
||||
fn write_le_f32(&self, f:f32) {
|
||||
unsafe {
|
||||
self.write_le_u32(cast::transmute(f))
|
||||
}
|
||||
}
|
||||
|
||||
fn write_u8(&self, n: u8) { self.write([n]) }
|
||||
fn write_i8(&self, n: i8) { self.write([n as u8]) }
|
||||
|
||||
}
|
||||
|
||||
pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
|
||||
mk_file_writer(path, flags).and_then(|w| Ok(w))
|
||||
}
|
||||
|
||||
// FIXME (#2004) it would be great if this could be a const
|
||||
// FIXME (#2004) why are these different from the way stdin() is
|
||||
// implemented?
|
||||
|
||||
pub struct BytesWriter {
|
||||
bytes: @mut ~[u8],
|
||||
pos: @mut uint,
|
||||
}
|
||||
|
||||
impl BytesWriter {
|
||||
pub fn new() -> BytesWriter {
|
||||
BytesWriter {
|
||||
bytes: @mut ~[],
|
||||
pos: @mut 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for BytesWriter {
|
||||
fn write(&self, v: &[u8]) {
|
||||
let v_len = v.len();
|
||||
|
||||
let bytes = &mut *self.bytes;
|
||||
let count = num::max(bytes.len(), *self.pos + v_len);
|
||||
bytes.reserve(count);
|
||||
|
||||
unsafe {
|
||||
vec::raw::set_len(bytes, count);
|
||||
|
||||
let view = bytes.mut_slice(*self.pos, count);
|
||||
vec::bytes::copy_memory(view, v, v_len);
|
||||
}
|
||||
|
||||
*self.pos += v_len;
|
||||
}
|
||||
|
||||
fn seek(&self, offset: int, whence: SeekStyle) {
|
||||
let pos = *self.pos;
|
||||
let len = self.bytes.len();
|
||||
*self.pos = seek_in_buf(offset, pos, len, whence);
|
||||
}
|
||||
|
||||
fn tell(&self) -> uint {
|
||||
*self.pos
|
||||
}
|
||||
|
||||
fn flush(&self) -> int {
|
||||
0
|
||||
}
|
||||
|
||||
fn get_type(&self) -> WriterType {
|
||||
File
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
|
||||
let wr = @BytesWriter::new();
|
||||
f(wr as @Writer);
|
||||
let @BytesWriter { bytes, _ } = wr;
|
||||
(*bytes).clone()
|
||||
}
|
||||
|
||||
pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
|
||||
str::from_utf8(with_bytes_writer(f))
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
|
||||
uint {
|
||||
let mut bpos = pos as int;
|
||||
let blen = len as int;
|
||||
match whence {
|
||||
SeekSet => bpos = offset,
|
||||
SeekCur => bpos += offset,
|
||||
SeekEnd => bpos = blen + offset
|
||||
}
|
||||
if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
|
||||
return bpos as uint;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::*;
|
||||
use i32;
|
||||
use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
|
||||
use io;
|
||||
use path::Path;
|
||||
use result::{Ok, Err};
|
||||
use u64;
|
||||
use vec;
|
||||
use cast::transmute;
|
||||
|
||||
#[test]
|
||||
fn test_simple() {
|
||||
let tmpfile = &Path::new("tmp/lib-io-test-simple.tmp");
|
||||
debug!("{}", tmpfile.display());
|
||||
let frood: ~str =
|
||||
~"A hoopy frood who really knows where his towel is.";
|
||||
debug!("{}", frood.clone());
|
||||
{
|
||||
let out = io::file_writer(tmpfile, [io::Create, io::Truncate]).unwrap();
|
||||
out.write_str(frood);
|
||||
}
|
||||
let inp = io::file_reader(tmpfile).unwrap();
|
||||
let frood2: ~str = inp.read_c_str();
|
||||
debug!("{}", frood2.clone());
|
||||
assert_eq!(frood, frood2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_each_byte_each_char_file() {
|
||||
// Issue #5056 -- shouldn't include trailing EOF.
|
||||
let path = Path::new("tmp/lib-io-test-each-byte-each-char-file.tmp");
|
||||
|
||||
{
|
||||
// create empty, enough to reproduce a problem
|
||||
io::file_writer(&path, [io::Create]).unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
do file.each_byte() |_| {
|
||||
fail!("must be empty")
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
do file.each_char() |_| {
|
||||
fail!("must be empty")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_reader_not_exist() {
|
||||
match io::file_reader(&Path::new("not a file")) {
|
||||
Err(e) => {
|
||||
assert_eq!(e, ~"error opening not a file");
|
||||
}
|
||||
Ok(_) => fail!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_read_buffer_too_small() {
|
||||
let path = &Path::new("tmp/lib-io-test-read-buffer-too-small.tmp");
|
||||
// ensure the file exists
|
||||
io::file_writer(path, [io::Create]).unwrap();
|
||||
|
||||
let file = io::file_reader(path).unwrap();
|
||||
let mut buf = vec::from_elem(5, 0u8);
|
||||
file.read(buf, 6); // this should fail because buf is too small
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_buffer_big_enough() {
|
||||
let path = &Path::new("tmp/lib-io-test-read-buffer-big-enough.tmp");
|
||||
// ensure the file exists
|
||||
io::file_writer(path, [io::Create]).unwrap();
|
||||
|
||||
let file = io::file_reader(path).unwrap();
|
||||
let mut buf = vec::from_elem(5, 0u8);
|
||||
file.read(buf, 4); // this should succeed because buf is big enough
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_empty() {
|
||||
let file = io::file_writer(&Path::new("tmp/lib-io-test-write-empty.tmp"),
|
||||
[io::Create]).unwrap();
|
||||
file.write([]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_writer_bad_name() {
|
||||
match io::file_writer(&Path::new("?/?"), []) {
|
||||
Err(e) => {
|
||||
assert!(e.starts_with("error opening"));
|
||||
}
|
||||
Ok(_) => fail!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bytes_buffer_overwrite() {
|
||||
let wr = BytesWriter::new();
|
||||
wr.write([0u8, 1u8, 2u8, 3u8]);
|
||||
assert!(*wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
|
||||
wr.seek(-2, SeekCur);
|
||||
wr.write([4u8, 5u8, 6u8, 7u8]);
|
||||
assert!(*wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
|
||||
wr.seek(-2, SeekEnd);
|
||||
wr.write([8u8]);
|
||||
wr.seek(1, SeekSet);
|
||||
wr.write([9u8]);
|
||||
assert!(*wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_write_le() {
|
||||
let path = Path::new("tmp/lib-io-test-read-write-le.tmp");
|
||||
let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
|
||||
|
||||
// write the ints to the file
|
||||
{
|
||||
let file = io::file_writer(&path, [io::Create]).unwrap();
|
||||
for i in uints.iter() {
|
||||
file.write_le_u64(*i);
|
||||
}
|
||||
}
|
||||
|
||||
// then read them back and check that they are the same
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
for i in uints.iter() {
|
||||
assert_eq!(file.read_le_u64(), *i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_write_be() {
|
||||
let path = Path::new("tmp/lib-io-test-read-write-be.tmp");
|
||||
let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
|
||||
|
||||
// write the ints to the file
|
||||
{
|
||||
let file = io::file_writer(&path, [io::Create]).unwrap();
|
||||
for i in uints.iter() {
|
||||
file.write_be_u64(*i);
|
||||
}
|
||||
}
|
||||
|
||||
// then read them back and check that they are the same
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
for i in uints.iter() {
|
||||
assert_eq!(file.read_be_u64(), *i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_be_int_n() {
|
||||
let path = Path::new("tmp/lib-io-test-read-be-int-n.tmp");
|
||||
let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
|
||||
|
||||
// write the ints to the file
|
||||
{
|
||||
let file = io::file_writer(&path, [io::Create]).unwrap();
|
||||
for i in ints.iter() {
|
||||
file.write_be_i32(*i);
|
||||
}
|
||||
}
|
||||
|
||||
// then read them back and check that they are the same
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
for i in ints.iter() {
|
||||
// this tests that the sign extension is working
|
||||
// (comparing the values as i32 would not test this)
|
||||
assert_eq!(file.read_be_int_n(4), *i as i64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_f32() {
|
||||
let path = Path::new("tmp/lib-io-test-read-f32.tmp");
|
||||
//big-endian floating-point 8.1250
|
||||
let buf = ~[0x41, 0x02, 0x00, 0x00];
|
||||
|
||||
{
|
||||
let file = io::file_writer(&path, [io::Create]).unwrap();
|
||||
file.write(buf);
|
||||
}
|
||||
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
let f = file.read_be_f32();
|
||||
assert_eq!(f, 8.1250);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_write_f32() {
|
||||
let path = Path::new("tmp/lib-io-test-read-write-f32.tmp");
|
||||
let f:f32 = 8.1250;
|
||||
|
||||
{
|
||||
let file = io::file_writer(&path, [io::Create]).unwrap();
|
||||
file.write_be_f32(f);
|
||||
file.write_le_f32(f);
|
||||
}
|
||||
|
||||
{
|
||||
let file = io::file_reader(&path).unwrap();
|
||||
assert_eq!(file.read_be_f32(), 8.1250);
|
||||
assert_eq!(file.read_le_f32(), 8.1250);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,6 @@
|
||||
pub use default::Default;
|
||||
pub use from_str::FromStr;
|
||||
pub use hash::Hash;
|
||||
pub use io::{Reader, ReaderUtil, Writer, WriterUtil};
|
||||
pub use iter::{FromIterator, Extendable};
|
||||
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, ClonableIterator};
|
||||
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
use option::{Option, Some, None};
|
||||
use unstable::finally::Finally;
|
||||
use cast;
|
||||
use io::{u64_to_le_bytes, u64_to_be_bytes};
|
||||
|
||||
pub trait ReaderUtil {
|
||||
|
||||
@@ -634,6 +633,88 @@ fn extend_sign(val: u64, nbytes: uint) -> i64 {
|
||||
(val << shift) as i64 >> shift
|
||||
}
|
||||
|
||||
pub fn u64_to_le_bytes<T>(n: u64, size: uint,
|
||||
f: &fn(v: &[u8]) -> T) -> T {
|
||||
assert!(size <= 8u);
|
||||
match size {
|
||||
1u => f(&[n as u8]),
|
||||
2u => f(&[n as u8,
|
||||
(n >> 8) as u8]),
|
||||
4u => f(&[n as u8,
|
||||
(n >> 8) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 24) as u8]),
|
||||
8u => f(&[n as u8,
|
||||
(n >> 8) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 24) as u8,
|
||||
(n >> 32) as u8,
|
||||
(n >> 40) as u8,
|
||||
(n >> 48) as u8,
|
||||
(n >> 56) as u8]),
|
||||
_ => {
|
||||
|
||||
let mut bytes: ~[u8] = ~[];
|
||||
let mut i = size;
|
||||
let mut n = n;
|
||||
while i > 0u {
|
||||
bytes.push((n & 255_u64) as u8);
|
||||
n >>= 8_u64;
|
||||
i -= 1u;
|
||||
}
|
||||
f(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_to_be_bytes<T>(n: u64, size: uint,
|
||||
f: &fn(v: &[u8]) -> T) -> T {
|
||||
assert!(size <= 8u);
|
||||
match size {
|
||||
1u => f(&[n as u8]),
|
||||
2u => f(&[(n >> 8) as u8,
|
||||
n as u8]),
|
||||
4u => f(&[(n >> 24) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 8) as u8,
|
||||
n as u8]),
|
||||
8u => f(&[(n >> 56) as u8,
|
||||
(n >> 48) as u8,
|
||||
(n >> 40) as u8,
|
||||
(n >> 32) as u8,
|
||||
(n >> 24) as u8,
|
||||
(n >> 16) as u8,
|
||||
(n >> 8) as u8,
|
||||
n as u8]),
|
||||
_ => {
|
||||
let mut bytes: ~[u8] = ~[];
|
||||
let mut i = size;
|
||||
while i > 0u {
|
||||
let shift = ((i - 1u) * 8u) as u64;
|
||||
bytes.push((n >> shift) as u8);
|
||||
i -= 1u;
|
||||
}
|
||||
f(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_from_be_bytes(data: &[u8],
|
||||
start: uint,
|
||||
size: uint)
|
||||
-> u64 {
|
||||
let mut sz = size;
|
||||
assert!((sz <= 8u));
|
||||
let mut val = 0_u64;
|
||||
let mut pos = start;
|
||||
while sz > 0u {
|
||||
sz -= 1u;
|
||||
val += (data[pos] as u64) << ((sz * 8u) as u64);
|
||||
pos += 1u;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::ReaderUtil;
|
||||
|
||||
@@ -148,7 +148,6 @@ pub mod linkhack {
|
||||
pub mod to_str;
|
||||
pub mod to_bytes;
|
||||
pub mod clone;
|
||||
pub mod io;
|
||||
pub mod hash;
|
||||
pub mod container;
|
||||
pub mod default;
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
use cast;
|
||||
use container::Container;
|
||||
use io;
|
||||
use io::Writer;
|
||||
use iter::Iterator;
|
||||
use option::{None, Option, Some};
|
||||
use str::{Str, StrSlice};
|
||||
@@ -360,7 +358,10 @@ pub trait ToBytes {
|
||||
|
||||
impl<A:IterBytes> ToBytes for A {
|
||||
fn to_bytes(&self, lsb0: bool) -> ~[u8] {
|
||||
do io::with_bytes_writer |wr| {
|
||||
use rt::io::mem;
|
||||
use rt::io::Writer;
|
||||
|
||||
do mem::with_mem_writer |wr| {
|
||||
do self.iter_bytes(lsb0) |bytes| {
|
||||
wr.write(bytes);
|
||||
true
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
// Tests that auto-ref can't create mutable aliases to immutable memory.
|
||||
|
||||
use std::io;
|
||||
|
||||
struct Foo {
|
||||
x: int
|
||||
}
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
use extra::glob::glob;
|
||||
use extra::tempfile::TempDir;
|
||||
use std::unstable::finally::Finally;
|
||||
use std::{io, os, unstable};
|
||||
use std::{os, unstable};
|
||||
use std::rt::io;
|
||||
use std::rt::io::file::FileInfo;
|
||||
|
||||
pub fn main() {
|
||||
fn mk_file(path: &str, directory: bool) {
|
||||
if directory {
|
||||
os::make_dir(&Path::new(path), 0xFFFF);
|
||||
} else {
|
||||
io::mk_file_writer(&Path::new(path), [io::Create]);
|
||||
Path::new(path).open_writer(io::Create);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user