mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 05:27:45 +00:00
printf: implement %b
This commit is contained in:
parent
a45ff8ca73
commit
cd0c24af07
2 changed files with 40 additions and 9 deletions
|
@ -169,17 +169,17 @@ fn parse_spec_only(fmt: &[u8]) -> impl Iterator<Item = Result<FormatItem<u8>, Fo
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_escape_only(fmt: &[u8]) -> impl Iterator<Item = Result<EscapedChar, FormatError>> + '_ {
|
fn parse_escape_only(fmt: &[u8]) -> impl Iterator<Item = EscapedChar> + '_ {
|
||||||
let mut current = fmt;
|
let mut current = fmt;
|
||||||
std::iter::from_fn(move || match current {
|
std::iter::from_fn(move || match current {
|
||||||
[] => return None,
|
[] => return None,
|
||||||
[b'\\', rest @ ..] => {
|
[b'\\', rest @ ..] => {
|
||||||
current = rest;
|
current = rest;
|
||||||
Some(Ok(parse_escape_code(&mut current)))
|
Some(parse_escape_code(&mut current))
|
||||||
}
|
}
|
||||||
[c, rest @ ..] => {
|
[c, rest @ ..] => {
|
||||||
current = rest;
|
current = rest;
|
||||||
Some(Ok(EscapedChar::Char(*c)))
|
Some(EscapedChar::Char(*c))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ use super::{
|
||||||
self, Case, FloatVariant, ForceDecimal, Formatter, NumberAlignment, PositiveSign, Prefix,
|
self, Case, FloatVariant, ForceDecimal, Formatter, NumberAlignment, PositiveSign, Prefix,
|
||||||
UnsignedIntVariant,
|
UnsignedIntVariant,
|
||||||
},
|
},
|
||||||
FormatArgument, FormatError,
|
parse_escape_only, FormatArgument, FormatChar, FormatError,
|
||||||
};
|
};
|
||||||
use std::{fmt::Display, io::Write};
|
use std::{fmt::Display, io::Write, ops::ControlFlow};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Spec {
|
pub enum Spec {
|
||||||
|
@ -17,6 +17,7 @@ pub enum Spec {
|
||||||
},
|
},
|
||||||
String {
|
String {
|
||||||
width: Option<CanAsterisk<usize>>,
|
width: Option<CanAsterisk<usize>>,
|
||||||
|
parse_escape: bool,
|
||||||
align_left: bool,
|
align_left: bool,
|
||||||
},
|
},
|
||||||
SignedInt {
|
SignedInt {
|
||||||
|
@ -145,6 +146,12 @@ impl Spec {
|
||||||
},
|
},
|
||||||
b's' => Spec::String {
|
b's' => Spec::String {
|
||||||
width,
|
width,
|
||||||
|
parse_escape: false,
|
||||||
|
align_left: minus,
|
||||||
|
},
|
||||||
|
b'b' => Spec::String {
|
||||||
|
width,
|
||||||
|
parse_escape: true,
|
||||||
align_left: minus,
|
align_left: minus,
|
||||||
},
|
},
|
||||||
b'd' | b'i' => Spec::SignedInt {
|
b'd' | b'i' => Spec::SignedInt {
|
||||||
|
@ -230,12 +237,36 @@ impl Spec {
|
||||||
_ => Err(FormatError::InvalidArgument(arg.clone())),
|
_ => Err(FormatError::InvalidArgument(arg.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Spec::String { width, align_left } => {
|
&Spec::String {
|
||||||
|
width,
|
||||||
|
parse_escape,
|
||||||
|
align_left,
|
||||||
|
} => {
|
||||||
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
|
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
|
||||||
let arg = next_arg(&mut args)?;
|
let arg = next_arg(&mut args)?;
|
||||||
match arg.get_str() {
|
let Some(s) = arg.get_str() else {
|
||||||
Some(s) => write_padded(writer, s, width, false, align_left),
|
return Err(FormatError::InvalidArgument(arg.clone()));
|
||||||
_ => Err(FormatError::InvalidArgument(arg.clone())),
|
};
|
||||||
|
if parse_escape {
|
||||||
|
let mut parsed = Vec::new();
|
||||||
|
for c in parse_escape_only(s.as_bytes()) {
|
||||||
|
match c.write(&mut parsed)? {
|
||||||
|
ControlFlow::Continue(()) => {}
|
||||||
|
ControlFlow::Break(()) => {
|
||||||
|
// TODO: This should break the _entire execution_ of printf
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
write_padded(
|
||||||
|
writer,
|
||||||
|
std::str::from_utf8(&parsed).expect("TODO: Accept invalid utf8"),
|
||||||
|
width,
|
||||||
|
false,
|
||||||
|
align_left,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
write_padded(writer, s, width, false, align_left)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Spec::SignedInt {
|
&Spec::SignedInt {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue