1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27: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> {
fn get_char(&mut self) -> char;
fn get_char(&mut self) -> u8;
fn get_i64(&mut self) -> i64;
fn get_u64(&mut self) -> u64;
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 {
fn get_char(&mut self) -> char {
fn get_char(&mut self) -> u8 {
let Some(next) = self.next() else {
return '\0';
return b'\0';
};
match next {
FormatArgument::Char(c) => *c,
FormatArgument::Unparsed(s) => s.bytes().next().map_or('\0', char::from),
_ => '\0',
FormatArgument::Char(c) => *c as u8,
FormatArgument::Unparsed(s) => s.bytes().next().unwrap_or(b'\0'),
_ => b'\0',
}
}

View file

@ -14,7 +14,7 @@ use super::{
},
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
///
@ -312,7 +312,7 @@ impl Spec {
match self {
Self::Char { width, align_left } => {
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 {
width,
@ -333,7 +333,7 @@ impl Spec {
Some(p) if p < s.len() => &s[..p],
_ => s,
};
write_padded(writer, truncated, width, false, *align_left)
write_padded(writer, truncated.as_bytes(), width, *align_left)
}
Self::EscapedString => {
let s = args.get_str();
@ -445,16 +445,17 @@ fn resolve_asterisk<'a>(
fn write_padded(
mut writer: impl Write,
text: impl Display,
text: &[u8],
width: usize,
pad_zero: bool,
left: bool,
) -> Result<(), FormatError> {
match (left, pad_zero) {
(false, false) => write!(writer, "{text: >width$}"),
(false, true) => write!(writer, "{text:0>width$}"),
// 0 is ignored if we pad left.
(true, _) => write!(writer, "{text: <width$}"),
let padlen = width.saturating_sub(text.len());
if left {
writer.write_all(text)?;
write!(writer, "{: <padlen$}", "")
} else {
write!(writer, "{: >padlen$}", "")?;
writer.write_all(text)
}
.map_err(FormatError::IoError)
}

View file

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