mirror of
https://github.com/Noratrieb/libuwuc.git
synced 2026-01-14 19:55:07 +01:00
printf
This commit is contained in:
parent
08938636d4
commit
bbe7f04877
2 changed files with 75 additions and 4 deletions
|
|
@ -5,17 +5,37 @@ use crate::{io::IoWrite, utils::SharedThinCstr};
|
||||||
pub unsafe fn printf_generic(
|
pub unsafe fn printf_generic(
|
||||||
mut sink: impl IoWrite,
|
mut sink: impl IoWrite,
|
||||||
format: SharedThinCstr<'_>,
|
format: SharedThinCstr<'_>,
|
||||||
_args: VaList<'_, '_>,
|
mut args: VaList<'_, '_>,
|
||||||
) -> Result<(), i32> {
|
) -> Result<(), i32> {
|
||||||
let mut chars = format.into_iter();
|
let mut chars = format.into_iter();
|
||||||
|
|
||||||
while let Some(c) = chars.next() {
|
while let Some(c) = chars.next() {
|
||||||
if c == b'%' {
|
if c == b'%' {
|
||||||
|
let Some(c) = chars.next() else {
|
||||||
|
return Err(-1);
|
||||||
|
};
|
||||||
|
// todo: do this properly
|
||||||
|
match c {
|
||||||
|
b'c' => {
|
||||||
|
let char = args.arg::<u8>();
|
||||||
|
write!(sink, "{}", char as char)?;
|
||||||
|
}
|
||||||
|
b'l' => {
|
||||||
|
let Some(c) = chars.next() else {
|
||||||
|
return Err(-1);
|
||||||
|
};
|
||||||
|
if c != b'd' {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
let long = args.arg::<i64>();
|
||||||
|
write!(sink, "{}", long)?;
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
sink.write_byte(c)?;
|
sink.write_byte(c)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -51,4 +71,16 @@ mod tests {
|
||||||
fn constant_string() {
|
fn constant_string() {
|
||||||
unsafe { test_printf("hello, world", cstr!("hello, world")) }
|
unsafe { test_printf("hello, world", cstr!("hello, world")) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore = "variadic")]
|
||||||
|
fn char() {
|
||||||
|
unsafe { test_printf("a", cstr!("%c"), b'a' as u64) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore = "variadic")]
|
||||||
|
fn long() {
|
||||||
|
unsafe { test_printf("234", cstr!("%ld"), 234_u64) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
pub trait IoWrite {
|
pub trait IoWrite {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize, i32>;
|
fn write(&mut self, buf: &[u8]) -> Result<usize, i32>;
|
||||||
|
|
||||||
|
|
@ -12,6 +14,43 @@ pub trait IoWrite {
|
||||||
fn write_byte(&mut self, byte: u8) -> Result<(), i32> {
|
fn write_byte(&mut self, byte: u8) -> Result<(), i32> {
|
||||||
self.write_all(&[byte])
|
self.write_all(&[byte])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<(), i32> {
|
||||||
|
// Create a shim which translates a Write to a fmt::Write and saves
|
||||||
|
// off I/O errors. instead of discarding them
|
||||||
|
struct Adapter<'a, T: ?Sized> {
|
||||||
|
inner: &'a mut T,
|
||||||
|
error: Result<(), i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: IoWrite + ?Sized> fmt::Write for Adapter<'_, T> {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
match self.inner.write_all(s.as_bytes()) {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(e) => {
|
||||||
|
self.error = Err(e);
|
||||||
|
Err(fmt::Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Adapter {
|
||||||
|
inner: self,
|
||||||
|
error: Ok(()),
|
||||||
|
};
|
||||||
|
match fmt::write(&mut output, fmt) {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(..) => {
|
||||||
|
// check if the error came from the underlying `Write` or not
|
||||||
|
if output.error.is_err() {
|
||||||
|
output.error
|
||||||
|
} else {
|
||||||
|
Err(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: IoWrite> IoWrite for &mut W {
|
impl<W: IoWrite> IoWrite for &mut W {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue