mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-30 04:27:45 +00:00
commit
df27f5035c
1 changed files with 36 additions and 34 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue