1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 04:27:45 +00:00

Merge pull request #582 from jbcrail/fix-split

Fix split.
This commit is contained in:
Heather 2015-05-09 08:10:50 +03:00
commit df27f5035c

View file

@ -1,5 +1,5 @@
#![crate_name = "split"]
#![feature(collections, core, old_io, old_path, rustc_private)]
#![feature(rustc_private)]
/*
* This file is part of the uutils coreutils package.
@ -13,9 +13,10 @@
extern crate getopts;
extern crate libc;
use std::old_io as io;
use std::num::Int;
use std::char;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader, BufWriter, Read, stdin, stdout, Write};
use std::path::Path;
#[path = "../common/util.rs"]
#[macro_use]
@ -36,7 +37,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
getopts::optflag("V", "version", "output version information and exit"),
];
let matches = match getopts::getopts(args.tail(), &opts) {
let matches = match getopts::getopts(&args[1..], &opts) {
Ok(m) => m,
Err(f) => crash!(1, "{}", f)
};
@ -47,7 +48,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
println!("Usage:");
println!(" {0} [OPTION]... [INPUT [PREFIX]]", NAME);
println!("");
io::print(getopts::usage("Output fixed-size pieces of INPUT to PREFIXaa, PREFIX ab, ...; default size is 1000, and default PREFIX is 'x'. With no INPUT, or when INPUT is -, read standard input." , &opts).as_slice());
print!("{}", getopts::usage("Output fixed-size pieces of INPUT to PREFIXaa, PREFIX ab, ...; default size is 1000, and default PREFIX is 'x'. With no INPUT, or when INPUT is -, read standard input." , &opts));
println!("");
println!("SIZE may have a multiplier suffix: b for 512, k for 1K, m for 1 Meg.");
return 0;
@ -71,7 +72,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
settings.numeric_suffix = if matches.opt_present("d") { true } else { false };
settings.suffix_length = match matches.opt_str("a") {
Some(n) => match n.as_slice().parse() {
Some(n) => match n.parse() {
Ok(m) => m,
Err(e) => crash!(1, "cannot parse num: {}", e)
},
@ -86,7 +87,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
for e in strategies.iter() {
match matches.opt_str(*e) {
Some(a) => {
if settings.strategy.as_slice() == "l" {
if settings.strategy == "l" {
settings.strategy = e.to_string();
settings.strategy_param = a;
} else {
@ -133,9 +134,10 @@ struct LineSplitter {
saved_lines_to_write: usize,
lines_to_write: usize,
}
impl LineSplitter {
fn new(settings: &Settings) -> Box<Splitter> {
let n = match settings.strategy_param.as_slice().parse() {
let n = match settings.strategy_param.parse() {
Ok(a) => a,
Err(e) => crash!(1, "invalid number of lines: {}", e)
};
@ -177,12 +179,12 @@ impl ByteSplitter {
_ => crash!(1, "invalid number of bytes")
};
let n = if suffix.is_alphabetic() {
match strategy_param.as_slice().iter().map(|c| *c).collect::<String>().as_slice().parse::<usize>() {
match strategy_param.iter().map(|c| *c).collect::<String>().parse::<usize>() {
Ok(a) => a,
Err(e) => crash!(1, "invalid number of bytes: {}", e)
}
} else {
match settings.strategy_param.as_slice().parse::<usize>() {
match settings.strategy_param.parse::<usize>() {
Ok(a) => a,
Err(e) => crash!(1, "invalid number of bytes: {}", e)
}
@ -199,22 +201,22 @@ impl ByteSplitter {
impl Splitter for ByteSplitter {
fn consume(&mut self, control: &mut SplitControl) -> String {
let line = control.current_line.clone();
let n = std::cmp::min(line.as_slice().chars().count(), self.bytes_to_write);
if self.require_whole_line && n < line.as_slice().chars().count() {
let n = std::cmp::min(line.chars().count(), self.bytes_to_write);
if self.require_whole_line && n < line.chars().count() {
self.bytes_to_write = self.saved_bytes_to_write;
control.request_new_file = true;
self.require_whole_line = false;
return line.as_slice()[0..0].to_string();
return line[0..0].to_string();
}
self.bytes_to_write -= n;
if n == 0 {
self.bytes_to_write = self.saved_bytes_to_write;
control.request_new_file = true;
}
if self.break_on_line_end && n == line.as_slice().chars().count() {
if self.break_on_line_end && n == line.chars().count() {
self.require_whole_line = self.break_on_line_end;
}
line.as_slice()[..n].to_string()
line[..n].to_string()
}
}
@ -225,7 +227,7 @@ fn str_prefix(i: usize, width: usize) -> String {
let mut w = width;
while w > 0 {
w -= 1;
let div = Int::pow(26 as usize, w as u32);
let div = 26usize.pow(w as u32);
let r = n / div;
n -= r * div;
c.push(char::from_u32((r as u32) + 97).unwrap());
@ -240,7 +242,7 @@ fn num_prefix(i: usize, width: usize) -> String {
let mut w = width;
while w > 0 {
w -= 1;
let div = Int::pow(10 as usize, w as u32);
let div = 10usize.pow(w as u32);
let r = n / div;
n -= r * div;
c.push(char::from_digit(r as u32, 10).unwrap());
@ -249,20 +251,20 @@ fn num_prefix(i: usize, width: usize) -> String {
}
fn split(settings: &Settings) -> i32 {
let mut reader = io::BufferedReader::new(
if settings.input.as_slice() == "-" {
Box::new(io::stdio::stdin_raw()) as Box<Reader>
let mut reader = BufReader::new(
if settings.input == "-" {
Box::new(stdin()) as Box<Read>
} else {
let r = match io::File::open(&Path::new(settings.input.clone())) {
let r = match File::open(Path::new(&settings.input)) {
Ok(a) => a,
Err(_) => crash!(1, "cannot open '{}' for reading: No such file or directory", settings.input)
};
Box::new(r) as Box<Reader>
Box::new(r) as Box<Read>
}
);
let mut splitter: Box<Splitter> =
match settings.strategy.as_slice() {
match settings.strategy.as_ref() {
"l" => LineSplitter::new(settings),
"b" | "C" => ByteSplitter::new(settings),
a @ _ => crash!(1, "strategy {} not supported", a)
@ -273,29 +275,29 @@ fn split(settings: &Settings) -> i32 {
request_new_file: true, // Request new file
};
let mut writer = io::BufferedWriter::new(Box::new(io::stdio::stdout_raw()) as Box<Writer>);
let mut writer = BufWriter::new(Box::new(stdout()) as Box<Write>);
let mut fileno = 0;
loop {
if control.current_line.as_slice().chars().count() == 0 {
match reader.read_line() {
Ok(a) => { control.current_line = a; }
Err(_) => { break; }
if control.current_line.chars().count() == 0 {
match reader.read_line(&mut control.current_line) {
Ok(0) | Err(_) => break,
_ => {}
}
}
if control.request_new_file {
let mut filename = settings.prefix.to_string();
let mut filename = settings.prefix.clone();
filename.push_str(if settings.numeric_suffix {
num_prefix(fileno, settings.suffix_length)
} else {
str_prefix(fileno, settings.suffix_length)
}.as_slice());
}.as_ref());
if fileno != 0 {
crash_if_err!(1, writer.flush());
}
fileno += 1;
writer = io::BufferedWriter::new(Box::new(io::File::open_mode(&Path::new(filename.as_slice()), io::Open, io::Write)) as Box<Writer>);
writer = BufWriter::new(Box::new(OpenOptions::new().write(true).create(true).open(Path::new(&filename)).unwrap()) as Box<Write>);
control.request_new_file = false;
if settings.verbose {
println!("creating file '{}'", filename);
@ -303,11 +305,11 @@ fn split(settings: &Settings) -> i32 {
}
let consumed = splitter.consume(&mut control);
crash_if_err!(1, writer.write_str(consumed.as_slice()));
crash_if_err!(1, writer.write_all(consumed.as_bytes()));
let advance = consumed.as_slice().chars().count();
let advance = consumed.chars().count();
let clone = control.current_line.clone();
let sl = clone.as_slice();
let sl = clone;
control.current_line = sl[advance..sl.chars().count()].to_string();
}
0