From 0602c197ff378ce97d653addc5e168f57779596f Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Thu, 8 Feb 2024 13:19:47 +0100 Subject: [PATCH] csplit: use uucore/format functionality for suffix --- src/uu/csplit/Cargo.toml | 2 +- src/uu/csplit/src/split_name.rs | 126 +++++--------------------------- 2 files changed, 18 insertions(+), 110 deletions(-) diff --git a/src/uu/csplit/Cargo.toml b/src/uu/csplit/Cargo.toml index 5e2f310cb..0a3c3bc60 100644 --- a/src/uu/csplit/Cargo.toml +++ b/src/uu/csplit/Cargo.toml @@ -18,7 +18,7 @@ path = "src/csplit.rs" clap = { workspace = true } thiserror = { workspace = true } regex = { workspace = true } -uucore = { workspace = true, features = ["entries", "fs"] } +uucore = { workspace = true, features = ["entries", "fs", "format"] } [[bin]] name = "csplit" diff --git a/src/uu/csplit/src/split_name.rs b/src/uu/csplit/src/split_name.rs index 4d94b56a9..a24a1cba6 100644 --- a/src/uu/csplit/src/split_name.rs +++ b/src/uu/csplit/src/split_name.rs @@ -4,14 +4,15 @@ // file that was distributed with this source code. // spell-checker:ignore (regex) diuox -use regex::Regex; +use uucore::format::{num_format::UnsignedInt, Format}; use crate::csplit_error::CsplitError; /// Computes the filename of a split, taking into consideration a possible user-defined suffix /// format. pub struct SplitName { - fn_split_name: Box String>, + prefix: Vec, + format: Format, } impl SplitName { @@ -36,6 +37,7 @@ impl SplitName { ) -> Result { // get the prefix let prefix = prefix_opt.unwrap_or_else(|| "xx".to_string()); + // the width for the split offset let n_digits = n_digits_opt .map(|opt| { @@ -44,120 +46,26 @@ impl SplitName { }) .transpose()? .unwrap_or(2); - // translate the custom format into a function - let fn_split_name: Box String> = match format_opt { - None => Box::new(move |n: usize| -> String { format!("{prefix}{n:0n_digits$}") }), - Some(custom) => { - let spec = - Regex::new(r"(?P%((?P[0#-])(?P\d+)?)?(?P[diuoxX]))") - .unwrap(); - let mut captures_iter = spec.captures_iter(&custom); - let custom_fn: Box String> = match captures_iter.next() { - Some(captures) => { - let all = captures.name("ALL").unwrap(); - let before = custom[0..all.start()].to_owned(); - let after = custom[all.end()..].to_owned(); - let width = match captures.name("WIDTH") { - None => 0, - Some(m) => m.as_str().parse::().unwrap(), - }; - match (captures.name("FLAG"), captures.name("TYPE")) { - (None, Some(ref t)) => match t.as_str() { - "d" | "i" | "u" => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n}{after}") - }), - "o" => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:o}{after}") - }), - "x" => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:x}{after}") - }), - "X" => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:X}{after}") - }), - _ => return Err(CsplitError::SuffixFormatIncorrect), - }, - (Some(ref f), Some(ref t)) => { - match (f.as_str(), t.as_str()) { - /* - * zero padding - */ - // decimal - ("0", "d" | "i" | "u") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:0width$}{after}") - }), - // octal - ("0", "o") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:0width$o}{after}") - }), - // lower hexadecimal - ("0", "x") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:0width$x}{after}") - }), - // upper hexadecimal - ("0", "X") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:0width$X}{after}") - }), - /* - * Alternate form - */ - // octal - ("#", "o") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:>#width$o}{after}") - }), - // lower hexadecimal - ("#", "x") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:>#width$x}{after}") - }), - // upper hexadecimal - ("#", "X") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:>#width$X}{after}") - }), - - /* - * Left adjusted - */ - // decimal - ("-", "d" | "i" | "u") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:<#width$}{after}") - }), - // octal - ("-", "o") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:<#width$o}{after}") - }), - // lower hexadecimal - ("-", "x") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:<#width$x}{after}") - }), - // upper hexadecimal - ("-", "X") => Box::new(move |n: usize| -> String { - format!("{prefix}{before}{n:<#width$X}{after}") - }), - - _ => return Err(CsplitError::SuffixFormatIncorrect), - } - } - _ => return Err(CsplitError::SuffixFormatIncorrect), - } - } - None => return Err(CsplitError::SuffixFormatIncorrect), - }; - - // there cannot be more than one format pattern - if captures_iter.next().is_some() { - return Err(CsplitError::SuffixFormatTooManyPercents); - } - custom_fn - } + let format_string = match format_opt { + Some(f) => f, + None => format!("%0{n_digits}u"), }; - Ok(Self { fn_split_name }) + let format = Format::::parse(format_string) + .map_err(|_| CsplitError::SuffixFormatIncorrect)?; + + Ok(Self { + prefix: prefix.as_bytes().to_owned(), + format, + }) } /// Returns the filename of the i-th split. pub fn get(&self, n: usize) -> String { - (self.fn_split_name)(n) + let mut v = self.prefix.clone(); + self.format.fmt(&mut v, n as u64).unwrap(); + String::from_utf8_lossy(&v).to_string() } }