mirror of
https://github.com/uutils/coreutils
synced 2024-12-14 23:32:39 +00:00
printf: support precision for integers
This commit is contained in:
parent
f83e0d1b04
commit
f3da0817a5
2 changed files with 38 additions and 4 deletions
|
@ -63,6 +63,7 @@ pub enum NumberAlignment {
|
||||||
|
|
||||||
pub struct SignedInt {
|
pub struct SignedInt {
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
|
pub precision: usize,
|
||||||
pub positive_sign: PositiveSign,
|
pub positive_sign: PositiveSign,
|
||||||
pub alignment: NumberAlignment,
|
pub alignment: NumberAlignment,
|
||||||
}
|
}
|
||||||
|
@ -79,16 +80,19 @@ impl Formatter for SignedInt {
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let s = format!("{:0width$}", x, width = self.precision);
|
||||||
|
|
||||||
match self.alignment {
|
match self.alignment {
|
||||||
NumberAlignment::Left => write!(writer, "{x:<width$}", width = self.width),
|
NumberAlignment::Left => write!(writer, "{s:<width$}", width = self.width),
|
||||||
NumberAlignment::RightSpace => write!(writer, "{x:>width$}", width = self.width),
|
NumberAlignment::RightSpace => write!(writer, "{s:>width$}", width = self.width),
|
||||||
NumberAlignment::RightZero => write!(writer, "{x:0>width$}", width = self.width),
|
NumberAlignment::RightZero => write!(writer, "{s:0>width$}", width = self.width),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_from_spec(s: Spec) -> Result<Self, FormatError> {
|
fn try_from_spec(s: Spec) -> Result<Self, FormatError> {
|
||||||
let Spec::SignedInt {
|
let Spec::SignedInt {
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
positive_sign,
|
positive_sign,
|
||||||
alignment,
|
alignment,
|
||||||
} = s
|
} = s
|
||||||
|
@ -102,8 +106,15 @@ impl Formatter for SignedInt {
|
||||||
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
|
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let precision = match precision {
|
||||||
|
Some(CanAsterisk::Fixed(x)) => x,
|
||||||
|
None => 0,
|
||||||
|
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
positive_sign,
|
positive_sign,
|
||||||
alignment,
|
alignment,
|
||||||
})
|
})
|
||||||
|
@ -113,6 +124,7 @@ impl Formatter for SignedInt {
|
||||||
pub struct UnsignedInt {
|
pub struct UnsignedInt {
|
||||||
pub variant: UnsignedIntVariant,
|
pub variant: UnsignedIntVariant,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
|
pub precision: usize,
|
||||||
pub alignment: NumberAlignment,
|
pub alignment: NumberAlignment,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +132,7 @@ impl Formatter for UnsignedInt {
|
||||||
type Input = u64;
|
type Input = u64;
|
||||||
|
|
||||||
fn fmt(&self, mut writer: impl Write, x: Self::Input) -> std::io::Result<()> {
|
fn fmt(&self, mut writer: impl Write, x: Self::Input) -> std::io::Result<()> {
|
||||||
let s = match self.variant {
|
let mut s = match self.variant {
|
||||||
UnsignedIntVariant::Decimal => format!("{x}"),
|
UnsignedIntVariant::Decimal => format!("{x}"),
|
||||||
UnsignedIntVariant::Octal(Prefix::No) => format!("{x:o}"),
|
UnsignedIntVariant::Octal(Prefix::No) => format!("{x:o}"),
|
||||||
UnsignedIntVariant::Octal(Prefix::Yes) => format!("{x:#o}"),
|
UnsignedIntVariant::Octal(Prefix::Yes) => format!("{x:#o}"),
|
||||||
|
@ -138,6 +150,10 @@ impl Formatter for UnsignedInt {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.precision > s.len() {
|
||||||
|
s = format!("{:0width$}", s, width = self.precision)
|
||||||
|
}
|
||||||
|
|
||||||
match self.alignment {
|
match self.alignment {
|
||||||
NumberAlignment::Left => write!(writer, "{s:<width$}", width = self.width),
|
NumberAlignment::Left => write!(writer, "{s:<width$}", width = self.width),
|
||||||
NumberAlignment::RightSpace => write!(writer, "{s:>width$}", width = self.width),
|
NumberAlignment::RightSpace => write!(writer, "{s:>width$}", width = self.width),
|
||||||
|
@ -149,6 +165,7 @@ impl Formatter for UnsignedInt {
|
||||||
let Spec::UnsignedInt {
|
let Spec::UnsignedInt {
|
||||||
variant,
|
variant,
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
alignment,
|
alignment,
|
||||||
} = s
|
} = s
|
||||||
else {
|
else {
|
||||||
|
@ -161,8 +178,15 @@ impl Formatter for UnsignedInt {
|
||||||
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
|
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let precision = match precision {
|
||||||
|
Some(CanAsterisk::Fixed(x)) => x,
|
||||||
|
None => 0,
|
||||||
|
Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
variant,
|
variant,
|
||||||
alignment,
|
alignment,
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,12 +22,14 @@ pub enum Spec {
|
||||||
},
|
},
|
||||||
SignedInt {
|
SignedInt {
|
||||||
width: Option<CanAsterisk<usize>>,
|
width: Option<CanAsterisk<usize>>,
|
||||||
|
precision: Option<CanAsterisk<usize>>,
|
||||||
positive_sign: PositiveSign,
|
positive_sign: PositiveSign,
|
||||||
alignment: NumberAlignment,
|
alignment: NumberAlignment,
|
||||||
},
|
},
|
||||||
UnsignedInt {
|
UnsignedInt {
|
||||||
variant: UnsignedIntVariant,
|
variant: UnsignedIntVariant,
|
||||||
width: Option<CanAsterisk<usize>>,
|
width: Option<CanAsterisk<usize>>,
|
||||||
|
precision: Option<CanAsterisk<usize>>,
|
||||||
alignment: NumberAlignment,
|
alignment: NumberAlignment,
|
||||||
},
|
},
|
||||||
Float {
|
Float {
|
||||||
|
@ -167,6 +169,7 @@ impl Spec {
|
||||||
},
|
},
|
||||||
b'd' | b'i' => Spec::SignedInt {
|
b'd' | b'i' => Spec::SignedInt {
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
alignment: match (minus, zero) {
|
alignment: match (minus, zero) {
|
||||||
(true, _) => NumberAlignment::Left,
|
(true, _) => NumberAlignment::Left,
|
||||||
(false, true) => NumberAlignment::RightZero,
|
(false, true) => NumberAlignment::RightZero,
|
||||||
|
@ -197,6 +200,7 @@ impl Spec {
|
||||||
};
|
};
|
||||||
Spec::UnsignedInt {
|
Spec::UnsignedInt {
|
||||||
variant,
|
variant,
|
||||||
|
precision,
|
||||||
width,
|
width,
|
||||||
alignment,
|
alignment,
|
||||||
}
|
}
|
||||||
|
@ -282,10 +286,12 @@ impl Spec {
|
||||||
}
|
}
|
||||||
&Spec::SignedInt {
|
&Spec::SignedInt {
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
positive_sign,
|
positive_sign,
|
||||||
alignment,
|
alignment,
|
||||||
} => {
|
} => {
|
||||||
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
|
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
|
||||||
|
let precision = resolve_asterisk(precision, &mut args)?.unwrap_or(0);
|
||||||
|
|
||||||
let arg = next_arg(&mut args)?;
|
let arg = next_arg(&mut args)?;
|
||||||
let Some(i) = arg.get_i64() else {
|
let Some(i) = arg.get_i64() else {
|
||||||
|
@ -294,6 +300,7 @@ impl Spec {
|
||||||
|
|
||||||
num_format::SignedInt {
|
num_format::SignedInt {
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
positive_sign,
|
positive_sign,
|
||||||
alignment,
|
alignment,
|
||||||
}
|
}
|
||||||
|
@ -303,9 +310,11 @@ impl Spec {
|
||||||
&Spec::UnsignedInt {
|
&Spec::UnsignedInt {
|
||||||
variant,
|
variant,
|
||||||
width,
|
width,
|
||||||
|
precision,
|
||||||
alignment,
|
alignment,
|
||||||
} => {
|
} => {
|
||||||
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
|
let width = resolve_asterisk(width, &mut args)?.unwrap_or(0);
|
||||||
|
let precision = resolve_asterisk(precision, &mut args)?.unwrap_or(0);
|
||||||
|
|
||||||
let arg = next_arg(args)?;
|
let arg = next_arg(args)?;
|
||||||
let Some(i) = arg.get_u64() else {
|
let Some(i) = arg.get_u64() else {
|
||||||
|
@ -314,6 +323,7 @@ impl Spec {
|
||||||
|
|
||||||
num_format::UnsignedInt {
|
num_format::UnsignedInt {
|
||||||
variant,
|
variant,
|
||||||
|
precision,
|
||||||
width,
|
width,
|
||||||
alignment,
|
alignment,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue