1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-02 14:07:46 +00:00

Merge pull request #551 from jbcrail/fix-head-tail

Fix head and tail.
This commit is contained in:
Heather 2015-04-29 23:16:09 +03:00
commit 3eb1d124ec
2 changed files with 41 additions and 46 deletions

View file

@ -1,5 +1,5 @@
#![crate_name = "head"] #![crate_name = "head"]
#![feature(collections, core, old_io, old_path, rustc_private)] #![feature(rustc_private)]
/* /*
* This file is part of the uutils coreutils package. * This file is part of the uutils coreutils package.
@ -14,11 +14,9 @@
extern crate getopts; extern crate getopts;
use std::char::CharExt; use std::io::{BufRead, BufReader, Read, stdin, Write};
use std::old_io::{stdin}; use std::fs::File;
use std::old_io::{BufferedReader, BytesReader}; use std::path::Path;
use std::old_io::fs::File;
use std::old_path::Path;
use std::str::from_utf8; use std::str::from_utf8;
use getopts::{optopt, optflag, getopts, usage}; use getopts::{optopt, optflag, getopts, usage};
@ -33,7 +31,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
let mut byte_count = 0usize; let mut byte_count = 0usize;
// handle obsolete -number syntax // handle obsolete -number syntax
let options = match obsolete(args.tail()) { let options = match obsolete(&args[1..]) {
(args, Some(n)) => { line_count = n; args }, (args, Some(n)) => { line_count = n; args },
(args, None) => args (args, None) => args
}; };
@ -47,7 +45,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
optflag("V", "version", "version") optflag("V", "version", "version")
]; ];
let given_options = match getopts(args.as_slice(), &possible_options) { let given_options = match getopts(args.as_ref(), &possible_options) {
Ok (m) => { m } Ok (m) => { m }
Err(_) => { Err(_) => {
println!("{}", usage(NAME, &possible_options)); println!("{}", usage(NAME, &possible_options));
@ -100,7 +98,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
}; };
if files.is_empty() { if files.is_empty() {
let mut buffer = BufferedReader::new(stdin()); let mut buffer = BufReader::new(stdin());
head(&mut buffer, count, use_bytes); head(&mut buffer, count, use_bytes);
} else { } else {
let mut multiple = false; let mut multiple = false;
@ -113,13 +111,13 @@ pub fn uumain(args: Vec<String>) -> i32 {
for file in files.iter() { for file in files.iter() {
if multiple { if multiple {
if !firstime { pipe_println!(""); } if !firstime { pipe_println!(""); }
pipe_println!("==> {} <==", file.as_slice()); pipe_println!("==> {} <==", file);
} }
firstime = false; firstime = false;
let path = Path::new(file.as_slice()); let path = Path::new(file);
let reader = File::open(&path).unwrap(); let reader = File::open(&path).unwrap();
let mut buffer = BufferedReader::new(reader); let mut buffer = BufReader::new(reader);
if !head(&mut buffer, count, use_bytes) { if !head(&mut buffer, count, use_bytes) {
break; break;
} }
@ -144,7 +142,7 @@ fn obsolete(options: &[String]) -> (Vec<String>, Option<usize>) {
if current.len() > 1 && current[0] == '-' as u8 { if current.len() > 1 && current[0] == '-' as u8 {
let len = current.len(); let len = current.len();
for pos in range(1, len) { for pos in (1 .. len) {
// Ensure that the argument is only made out of digits // Ensure that the argument is only made out of digits
if !(current[pos] as char).is_numeric() { break; } if !(current[pos] as char).is_numeric() { break; }
@ -164,7 +162,7 @@ fn obsolete(options: &[String]) -> (Vec<String>, Option<usize>) {
} }
// TODO: handle errors on read // TODO: handle errors on read
fn head<T: Reader>(reader: &mut BufferedReader<T>, count: usize, use_bytes: bool) -> bool { fn head<T: Read>(reader: &mut BufReader<T>, count: usize, use_bytes: bool) -> bool {
if use_bytes { if use_bytes {
for byte in reader.bytes().take(count) { for byte in reader.bytes().take(count) {
if !pipe_print!("{}", byte.unwrap() as char) { if !pipe_print!("{}", byte.unwrap() as char) {

View file

@ -1,5 +1,5 @@
#![crate_name = "tail"] #![crate_name = "tail"]
#![feature(collections, core, old_io, old_path, rustc_private, std_misc)] #![feature(rustc_private)]
/* /*
* This file is part of the uutils coreutils package. * This file is part of the uutils coreutils package.
@ -13,16 +13,13 @@
extern crate getopts; extern crate getopts;
use std::char::CharExt;
use std::old_io::{stdin, stdout};
use std::old_io::{BufferedReader, BytesReader};
use std::old_io::fs::File;
use std::old_path::Path;
use std::str::from_utf8;
use getopts::{optopt, optflag, getopts, usage}; use getopts::{optopt, optflag, getopts, usage};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::old_io::timer::sleep; use std::fs::File;
use std::time::duration::Duration; use std::io::{BufRead, BufReader, Read, stdin, stdout, Write};
use std::path::Path;
use std::str::from_utf8;
use std::thread::sleep_ms;
#[path = "../common/util.rs"] #[path = "../common/util.rs"]
#[macro_use] #[macro_use]
@ -36,10 +33,10 @@ pub fn uumain(args: Vec<String>) -> i32 {
let mut lines = true; let mut lines = true;
let mut byte_count = 0usize; let mut byte_count = 0usize;
let mut line_count = 10usize; let mut line_count = 10usize;
let mut sleep_msec = 1000u64; let mut sleep_msec = 1000u32;
// handle obsolete -number syntax // handle obsolete -number syntax
let options = match obsolete(args.tail()) { let options = match obsolete(&args[1..]) {
(args, Some(n)) => { line_count = n; args }, (args, Some(n)) => { line_count = n; args },
(args, None) => args (args, None) => args
}; };
@ -55,7 +52,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
optflag("V", "version", "version"), optflag("V", "version", "version"),
]; ];
let given_options = match getopts(args.as_slice(), &possible_options) { let given_options = match getopts(args.as_ref(), &possible_options) {
Ok (m) => { m } Ok (m) => { m }
Err(_) => { Err(_) => {
println!("{}", usage(NAME, &possible_options)); println!("{}", usage(NAME, &possible_options));
@ -73,7 +70,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
if follow { if follow {
match given_options.opt_str("s") { match given_options.opt_str("s") {
Some(n) => { Some(n) => {
let parsed: Option<u64> = n.parse().ok(); let parsed: Option<u32> = n.parse().ok();
match parsed { match parsed {
Some(m) => { sleep_msec = m * 1000 } Some(m) => { sleep_msec = m * 1000 }
None => {} None => {}
@ -85,8 +82,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
match given_options.opt_str("n") { match given_options.opt_str("n") {
Some(n) => { Some(n) => {
let mut slice = n.as_slice(); let mut slice: &str = n.as_ref();
if slice.len() > 0 && slice.char_at(0) == '+' { if slice.chars().next().unwrap_or('_') == '+' {
beginning = true; beginning = true;
slice = &slice[1..]; slice = &slice[1..];
} }
@ -100,8 +97,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
} }
None => match given_options.opt_str("c") { None => match given_options.opt_str("c") {
Some(n) => { Some(n) => {
let mut slice = n.as_slice(); let mut slice: &str = n.as_ref();
if slice.len() > 0 && slice.char_at(0) == '+' { if slice.chars().next().unwrap_or('_') == '+' {
beginning = true; beginning = true;
slice = &slice[1..]; slice = &slice[1..];
} }
@ -121,7 +118,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
let files = given_options.free; let files = given_options.free;
if files.is_empty() { if files.is_empty() {
let mut buffer = BufferedReader::new(stdin()); let mut buffer = BufReader::new(stdin());
tail(&mut buffer, line_count, byte_count, beginning, lines, follow, sleep_msec); tail(&mut buffer, line_count, byte_count, beginning, lines, follow, sleep_msec);
} else { } else {
let mut multiple = false; let mut multiple = false;
@ -135,13 +132,13 @@ pub fn uumain(args: Vec<String>) -> i32 {
for file in files.iter() { for file in files.iter() {
if multiple { if multiple {
if !firstime { println!(""); } if !firstime { println!(""); }
println!("==> {} <==", file.as_slice()); println!("==> {} <==", file);
} }
firstime = false; firstime = false;
let path = Path::new(file.as_slice()); let path = Path::new(file);
let reader = File::open(&path).unwrap(); let reader = File::open(&path).unwrap();
let mut buffer = BufferedReader::new(reader); let mut buffer = BufReader::new(reader);
tail(&mut buffer, line_count, byte_count, beginning, lines, follow, sleep_msec); tail(&mut buffer, line_count, byte_count, beginning, lines, follow, sleep_msec);
} }
} }
@ -151,7 +148,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
fn parse_size(mut size_slice: &str) -> Option<usize> { fn parse_size(mut size_slice: &str) -> Option<usize> {
let mut base = let mut base =
if size_slice.len() > 0 && size_slice.char_at(size_slice.len() - 1) == 'B' { if size_slice.chars().last().unwrap_or('_') == 'B' {
size_slice = &size_slice[..size_slice.len() - 1]; size_slice = &size_slice[..size_slice.len() - 1];
1000usize 1000usize
} else { } else {
@ -160,7 +157,7 @@ fn parse_size(mut size_slice: &str) -> Option<usize> {
let exponent = let exponent =
if size_slice.len() > 0 { if size_slice.len() > 0 {
let mut has_suffix = true; let mut has_suffix = true;
let exp = match size_slice.char_at(size_slice.len() - 1) { let exp = match size_slice.chars().last().unwrap_or('_') {
'K' => 1usize, 'K' => 1usize,
'M' => 2usize, 'M' => 2usize,
'G' => 3usize, 'G' => 3usize,
@ -187,16 +184,16 @@ fn parse_size(mut size_slice: &str) -> Option<usize> {
}; };
let mut multiplier = 1usize; let mut multiplier = 1usize;
for _ in range(0usize, exponent) { for _ in (0usize .. exponent) {
multiplier *= base; multiplier *= base;
} }
if base == 1000usize && exponent == 0usize { if base == 1000usize && exponent == 0usize {
// sole B is not a valid suffix // sole B is not a valid suffix
None None
} else { } else {
let value = size_slice.parse(); let value: Option<usize> = size_slice.parse().ok();
match value { match value {
Ok(v) => Some(multiplier * v), Some(v) => Some(multiplier * v),
_ => None _ => None
} }
} }
@ -217,7 +214,7 @@ fn obsolete(options: &[String]) -> (Vec<String>, Option<usize>) {
if current.len() > 1 && current[0] == '-' as u8 { if current.len() > 1 && current[0] == '-' as u8 {
let len = current.len(); let len = current.len();
for pos in range(1, len) { for pos in (1 .. len) {
// Ensure that the argument is only made out of digits // Ensure that the argument is only made out of digits
if !(current[pos] as char).is_numeric() { break; } if !(current[pos] as char).is_numeric() { break; }
@ -269,7 +266,7 @@ macro_rules! tail_impl (
}) })
); );
fn tail<T: Reader>(reader: &mut BufferedReader<T>, mut line_count: usize, mut byte_count: usize, beginning: bool, lines: bool, follow: bool, sleep_msec: u64) { fn tail<T: Read>(reader: &mut BufReader<T>, mut line_count: usize, mut byte_count: usize, beginning: bool, lines: bool, follow: bool, sleep_msec: u32) {
if lines { if lines {
tail_impl!(String, lines, print_string, reader, line_count, beginning); tail_impl!(String, lines, print_string, reader, line_count, beginning);
} else { } else {
@ -278,7 +275,7 @@ fn tail<T: Reader>(reader: &mut BufferedReader<T>, mut line_count: usize, mut by
// if we follow the file, sleep a bit and print the rest if the file has grown. // if we follow the file, sleep a bit and print the rest if the file has grown.
while follow { while follow {
sleep(Duration::milliseconds(sleep_msec as i64)); sleep_ms(sleep_msec);
for io_line in reader.lines() { for io_line in reader.lines() {
match io_line { match io_line {
Ok(line) => print!("{}", line), Ok(line) => print!("{}", line),
@ -289,14 +286,14 @@ fn tail<T: Reader>(reader: &mut BufferedReader<T>, mut line_count: usize, mut by
} }
#[inline] #[inline]
fn print_byte<T: Writer>(stdout: &mut T, ch: &u8) { fn print_byte<T: Write>(stdout: &mut T, ch: &u8) {
if let Err(err) = stdout.write_u8(*ch) { if let Err(err) = stdout.write(&[*ch]) {
crash!(1, "{}", err); crash!(1, "{}", err);
} }
} }
#[inline] #[inline]
fn print_string<T: Writer>(_: &mut T, s: &String) { fn print_string<T: Write>(_: &mut T, s: &String) {
print!("{}", s); print!("{}", s);
} }