1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

printf: Change get_char and write_padded to handle bytes instead of chars

This commit is contained in:
Dorian Péron 2024-02-29 00:45:35 +01:00
parent 5d74a6e002
commit 42cde767d2
3 changed files with 23 additions and 28 deletions

View file

@ -31,7 +31,7 @@ pub enum FormatArgument {
} }
pub trait ArgumentIter<'a>: Iterator<Item = &'a FormatArgument> { pub trait ArgumentIter<'a>: Iterator<Item = &'a FormatArgument> {
fn get_char(&mut self) -> char; fn get_char(&mut self) -> u8;
fn get_i64(&mut self) -> i64; fn get_i64(&mut self) -> i64;
fn get_u64(&mut self) -> u64; fn get_u64(&mut self) -> u64;
fn get_f64(&mut self) -> f64; fn get_f64(&mut self) -> f64;
@ -39,14 +39,14 @@ pub trait ArgumentIter<'a>: Iterator<Item = &'a FormatArgument> {
} }
impl<'a, T: Iterator<Item = &'a FormatArgument>> ArgumentIter<'a> for T { impl<'a, T: Iterator<Item = &'a FormatArgument>> ArgumentIter<'a> for T {
fn get_char(&mut self) -> char { fn get_char(&mut self) -> u8 {
let Some(next) = self.next() else { let Some(next) = self.next() else {
return '\0'; return b'\0';
}; };
match next { match next {
FormatArgument::Char(c) => *c, FormatArgument::Char(c) => *c as u8,
FormatArgument::Unparsed(s) => s.bytes().next().map_or('\0', char::from), FormatArgument::Unparsed(s) => s.bytes().next().unwrap_or(b'\0'),
_ => '\0', _ => b'\0',
} }
} }

View file

@ -14,7 +14,7 @@ use super::{
}, },
parse_escape_only, ArgumentIter, FormatChar, FormatError, parse_escape_only, ArgumentIter, FormatChar, FormatError,
}; };
use std::{fmt::Display, io::Write, ops::ControlFlow}; use std::{io::Write, ops::ControlFlow};
/// A parsed specification for formatting a value /// A parsed specification for formatting a value
/// ///
@ -312,7 +312,7 @@ impl Spec {
match self { match self {
Self::Char { width, align_left } => { Self::Char { width, align_left } => {
let width = resolve_asterisk(*width, &mut args)?.unwrap_or(0); let width = resolve_asterisk(*width, &mut args)?.unwrap_or(0);
write_padded(writer, args.get_char(), width, false, *align_left) write_padded(writer, &[args.get_char()], width, *align_left)
} }
Self::String { Self::String {
width, width,
@ -333,7 +333,7 @@ impl Spec {
Some(p) if p < s.len() => &s[..p], Some(p) if p < s.len() => &s[..p],
_ => s, _ => s,
}; };
write_padded(writer, truncated, width, false, *align_left) write_padded(writer, truncated.as_bytes(), width, *align_left)
} }
Self::EscapedString => { Self::EscapedString => {
let s = args.get_str(); let s = args.get_str();
@ -445,16 +445,17 @@ fn resolve_asterisk<'a>(
fn write_padded( fn write_padded(
mut writer: impl Write, mut writer: impl Write,
text: impl Display, text: &[u8],
width: usize, width: usize,
pad_zero: bool,
left: bool, left: bool,
) -> Result<(), FormatError> { ) -> Result<(), FormatError> {
match (left, pad_zero) { let padlen = width.saturating_sub(text.len());
(false, false) => write!(writer, "{text: >width$}"), if left {
(false, true) => write!(writer, "{text:0>width$}"), writer.write_all(text)?;
// 0 is ignored if we pad left. write!(writer, "{: <padlen$}", "")
(true, _) => write!(writer, "{text: <width$}"), } else {
write!(writer, "{: >padlen$}", "")?;
writer.write_all(text)
} }
.map_err(FormatError::IoError) .map_err(FormatError::IoError)
} }

View file

@ -743,12 +743,7 @@ fn pad_unsigned_three() {
#[test] #[test]
fn pad_char() { fn pad_char() {
for (format, expected) in [ for (format, expected) in [("%3c", " X"), ("%1c", "X"), ("%-1c", "X"), ("%-3c", "X ")] {
("%3c", " X"),
("%1c", "X"),
("%-1c", "X"),
("%-3c", "X "),
] {
new_ucmd!() new_ucmd!()
.args(&[format, "X"]) .args(&[format, "X"])
.succeeds() .succeeds()
@ -756,14 +751,13 @@ fn pad_char() {
} }
} }
#[test] #[test]
fn pad_string() { fn pad_string() {
for (format, expected) in [ for (format, expected) in [
("%8s", " bottle"), ("%8s", " bottle"),
("%-8s", "bottle "), ("%-8s", "bottle "),
("%6s", "bottle"), ("%6s", "bottle"),
("%-6s", "bottle"), ("%-6s", "bottle"),
] { ] {
new_ucmd!() new_ucmd!()
.args(&[format, "bottle"]) .args(&[format, "bottle"])