Use unsafe blocks in stdio.h implementation
This commit is contained in:
committed by
sourceturner
parent
b3add24654
commit
b3f7db83cf
@@ -1,5 +1,8 @@
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html
|
||||
|
||||
// TODO: set this for entire crate when possible
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::{fmt::Write, intrinsics::unlikely, ops::Deref, ptr};
|
||||
|
||||
@@ -27,7 +30,7 @@ pub unsafe extern "C" fn getline(
|
||||
n: *mut size_t,
|
||||
stream: *mut FILE,
|
||||
) -> ssize_t {
|
||||
getdelim(lineptr, n, b'\n' as c_int, stream)
|
||||
unsafe { getdelim(lineptr, n, b'\n' as c_int, stream) }
|
||||
}
|
||||
|
||||
// One *could* read the standard as 'getdelim sets the stream error flag on *any* error, though
|
||||
@@ -55,15 +58,17 @@ pub unsafe extern "C" fn getdelim(
|
||||
delim: c_int,
|
||||
stream: *mut FILE,
|
||||
) -> ssize_t {
|
||||
let (lineptr, n, stream) =
|
||||
if let (Some(ptr), Some(n), Some(file)) = (lineptr.as_mut(), n.as_mut(), stream.as_mut()) {
|
||||
(ptr, n, file)
|
||||
} else {
|
||||
ERRNO.set(EINVAL);
|
||||
return -1 as ssize_t;
|
||||
};
|
||||
let (lineptr, n, stream) = if let (Some(ptr), Some(n), Some(file)) =
|
||||
(unsafe { lineptr.as_mut() }, unsafe { n.as_mut() }, unsafe {
|
||||
stream.as_mut()
|
||||
}) {
|
||||
(ptr, n, file)
|
||||
} else {
|
||||
ERRNO.set(EINVAL);
|
||||
return -1 as ssize_t;
|
||||
};
|
||||
|
||||
if feof(stream) != 0 || ferror(stream) != 0 {
|
||||
if unsafe { feof(stream) } != 0 || unsafe { ferror(stream) } != 0 {
|
||||
return -1 as ssize_t;
|
||||
}
|
||||
|
||||
@@ -121,7 +126,7 @@ pub unsafe extern "C" fn getdelim(
|
||||
*n = count + 1;
|
||||
// The advantage in always realloc'ing is that even if the user supplies a wrong n, this
|
||||
// doesn't break
|
||||
*lineptr = stdlib::realloc(*lineptr as *mut c_void, *n) as *mut c_char;
|
||||
*lineptr = unsafe { stdlib::realloc(*lineptr as *mut c_void, *n) } as *mut c_char;
|
||||
if unlikely(lineptr.is_null() && *n != 0usize) {
|
||||
// memory error; realloc returns NULL on alloc'ing 0 bytes
|
||||
ERRNO.set(ENOMEM);
|
||||
@@ -129,10 +134,10 @@ pub unsafe extern "C" fn getdelim(
|
||||
}
|
||||
|
||||
// Copy buf to lineptr
|
||||
ptr::copy(buf.as_ptr(), *lineptr as *mut u8, count);
|
||||
unsafe { ptr::copy(buf.as_ptr(), *lineptr as *mut u8, count) };
|
||||
|
||||
// NUL terminate lineptr
|
||||
*lineptr.offset(count as isize) = 0;
|
||||
unsafe { *lineptr.offset(count as isize) = 0 };
|
||||
|
||||
// TODO remove
|
||||
/*eprintln!(
|
||||
|
||||
+227
-193
File diff suppressed because it is too large
Load Diff
+102
-75
@@ -1,3 +1,6 @@
|
||||
// TODO: set this for entire crate when possible
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
// TODO: reuse more code with the wide printf impl
|
||||
use crate::{
|
||||
c_str::{self, CStr, NulStr},
|
||||
@@ -59,11 +62,11 @@ impl Number {
|
||||
pub(crate) unsafe fn resolve(self, varargs: &mut VaListCache, ap: &mut VaList) -> usize {
|
||||
let arg = match self {
|
||||
Number::Static(num) => return num,
|
||||
Number::Index(i) => varargs.get(i - 1, ap, None),
|
||||
Number::Index(i) => unsafe { varargs.get(i - 1, ap, None) },
|
||||
Number::Next => {
|
||||
let i = varargs.i;
|
||||
varargs.i += 1;
|
||||
varargs.get(i, ap, None)
|
||||
unsafe { varargs.get(i, ap, None) }
|
||||
}
|
||||
};
|
||||
match arg {
|
||||
@@ -108,44 +111,44 @@ impl VaArg {
|
||||
(FmtKind::Percent, _) => panic!("Can't call arg_from on %"),
|
||||
|
||||
(FmtKind::Char, IntKind::Long) | (FmtKind::Char, IntKind::LongLong) => {
|
||||
VaArg::wint_t(ap.arg::<wint_t>())
|
||||
VaArg::wint_t(unsafe { ap.arg::<wint_t>() })
|
||||
}
|
||||
|
||||
(FmtKind::Char, _)
|
||||
| (FmtKind::Unsigned, IntKind::Byte)
|
||||
| (FmtKind::Signed, IntKind::Byte) => {
|
||||
// c_int is passed but truncated to c_char
|
||||
VaArg::c_char(ap.arg::<c_int>() as c_char)
|
||||
VaArg::c_char(unsafe { ap.arg::<c_int>() } as c_char)
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Short) | (FmtKind::Signed, IntKind::Short) => {
|
||||
// c_int is passed but truncated to c_short
|
||||
VaArg::c_short(ap.arg::<c_int>() as c_short)
|
||||
VaArg::c_short(unsafe { ap.arg::<c_int>() } as c_short)
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Int) | (FmtKind::Signed, IntKind::Int) => {
|
||||
VaArg::c_int(ap.arg::<c_int>())
|
||||
VaArg::c_int(unsafe { ap.arg::<c_int>() })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Long) | (FmtKind::Signed, IntKind::Long) => {
|
||||
VaArg::c_long(ap.arg::<c_long>())
|
||||
VaArg::c_long(unsafe { ap.arg::<c_long>() })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::LongLong) | (FmtKind::Signed, IntKind::LongLong) => {
|
||||
VaArg::c_longlong(ap.arg::<c_longlong>())
|
||||
VaArg::c_longlong(unsafe { ap.arg::<c_longlong>() })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::IntMax) | (FmtKind::Signed, IntKind::IntMax) => {
|
||||
VaArg::intmax_t(ap.arg::<intmax_t>())
|
||||
VaArg::intmax_t(unsafe { ap.arg::<intmax_t>() })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::PtrDiff) | (FmtKind::Signed, IntKind::PtrDiff) => {
|
||||
VaArg::ptrdiff_t(ap.arg::<ptrdiff_t>())
|
||||
VaArg::ptrdiff_t(unsafe { ap.arg::<ptrdiff_t>() })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Size) | (FmtKind::Signed, IntKind::Size) => {
|
||||
VaArg::ssize_t(ap.arg::<ssize_t>())
|
||||
VaArg::ssize_t(unsafe { ap.arg::<ssize_t>() })
|
||||
}
|
||||
|
||||
(FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _) => {
|
||||
VaArg::c_double(ap.arg::<c_double>())
|
||||
VaArg::c_double(unsafe { ap.arg::<c_double>() })
|
||||
}
|
||||
|
||||
(FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _) => {
|
||||
VaArg::pointer(ap.arg::<*const c_void>())
|
||||
VaArg::pointer(unsafe { ap.arg::<*const c_void>() })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,40 +191,40 @@ impl VaArg {
|
||||
(FmtKind::Percent, _) => panic!("Can't call transmute on %"),
|
||||
|
||||
(FmtKind::Char, IntKind::Long) | (FmtKind::Char, IntKind::LongLong) => {
|
||||
VaArg::wint_t(untyped.wint_t)
|
||||
VaArg::wint_t(unsafe { untyped.wint_t })
|
||||
}
|
||||
|
||||
(FmtKind::Char, _)
|
||||
| (FmtKind::Unsigned, IntKind::Byte)
|
||||
| (FmtKind::Signed, IntKind::Byte) => VaArg::c_char(untyped.c_char),
|
||||
| (FmtKind::Signed, IntKind::Byte) => VaArg::c_char(unsafe { untyped.c_char }),
|
||||
(FmtKind::Unsigned, IntKind::Short) | (FmtKind::Signed, IntKind::Short) => {
|
||||
VaArg::c_short(untyped.c_short)
|
||||
VaArg::c_short(unsafe { untyped.c_short })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Int) | (FmtKind::Signed, IntKind::Int) => {
|
||||
VaArg::c_int(untyped.c_int)
|
||||
VaArg::c_int(unsafe { untyped.c_int })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Long) | (FmtKind::Signed, IntKind::Long) => {
|
||||
VaArg::c_long(untyped.c_long)
|
||||
VaArg::c_long(unsafe { untyped.c_long })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::LongLong) | (FmtKind::Signed, IntKind::LongLong) => {
|
||||
VaArg::c_longlong(untyped.c_longlong)
|
||||
VaArg::c_longlong(unsafe { untyped.c_longlong })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::IntMax) | (FmtKind::Signed, IntKind::IntMax) => {
|
||||
VaArg::intmax_t(untyped.intmax_t)
|
||||
VaArg::intmax_t(unsafe { untyped.intmax_t })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::PtrDiff) | (FmtKind::Signed, IntKind::PtrDiff) => {
|
||||
VaArg::ptrdiff_t(untyped.ptrdiff_t)
|
||||
VaArg::ptrdiff_t(unsafe { untyped.ptrdiff_t })
|
||||
}
|
||||
(FmtKind::Unsigned, IntKind::Size) | (FmtKind::Signed, IntKind::Size) => {
|
||||
VaArg::ssize_t(untyped.ssize_t)
|
||||
VaArg::ssize_t(unsafe { untyped.ssize_t })
|
||||
}
|
||||
|
||||
(FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _) => {
|
||||
VaArg::c_double(untyped.c_double)
|
||||
VaArg::c_double(unsafe { untyped.c_double })
|
||||
}
|
||||
|
||||
(FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _) => {
|
||||
VaArg::pointer(untyped.pointer)
|
||||
VaArg::pointer(unsafe { untyped.pointer })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +246,7 @@ impl VaListCache {
|
||||
let mut arg = arg;
|
||||
if let Some((fmtkind, intkind)) = default {
|
||||
// ...but as a different type
|
||||
arg = arg.transmute(fmtkind, intkind);
|
||||
arg = unsafe { arg.transmute(fmtkind, intkind) };
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
@@ -254,13 +257,13 @@ impl VaListCache {
|
||||
// point. Reaching here means there are unused gaps in the
|
||||
// arguments. Ultimately we'll have to settle down with
|
||||
// defaulting to c_int.
|
||||
self.args.push(VaArg::c_int(ap.arg::<c_int>()))
|
||||
self.args.push(VaArg::c_int(unsafe { ap.arg::<c_int>() }))
|
||||
}
|
||||
|
||||
// Add the value to the cache
|
||||
self.args.push(match default {
|
||||
Some((fmtkind, intkind)) => VaArg::arg_from(fmtkind, intkind, ap),
|
||||
None => VaArg::c_int(ap.arg::<c_int>()),
|
||||
Some((fmtkind, intkind)) => unsafe { VaArg::arg_from(fmtkind, intkind, ap) },
|
||||
None => VaArg::c_int(unsafe { ap.arg::<c_int>() }),
|
||||
});
|
||||
|
||||
// Return the value
|
||||
@@ -656,7 +659,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
}
|
||||
for num in &[arg.min_width, arg.precision.unwrap_or(Number::Static(0))] {
|
||||
match num {
|
||||
Number::Next => varargs.args.push(VaArg::c_int(ap.arg::<c_int>())),
|
||||
Number::Next => varargs
|
||||
.args
|
||||
.push(VaArg::c_int(unsafe { ap.arg::<c_int>() })),
|
||||
Number::Index(i) => {
|
||||
positional.insert(i - 1, (FmtKind::Signed, IntKind::Int));
|
||||
}
|
||||
@@ -669,13 +674,13 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
}
|
||||
None => varargs
|
||||
.args
|
||||
.push(VaArg::arg_from(arg.fmtkind, arg.intkind, &mut ap)),
|
||||
.push(unsafe { VaArg::arg_from(arg.fmtkind, arg.intkind, &mut ap) }),
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure, in order, the positional arguments exist with the specified type
|
||||
for (i, arg) in positional {
|
||||
varargs.get(i, &mut ap, Some(arg));
|
||||
unsafe { varargs.get(i, &mut ap, Some(arg)) };
|
||||
}
|
||||
|
||||
// Main loop
|
||||
@@ -701,10 +706,10 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
let mut left = arg.left;
|
||||
let sign_reserve = arg.sign_reserve;
|
||||
let sign_always = arg.sign_always;
|
||||
let min_width = arg.min_width.resolve(&mut varargs, &mut ap);
|
||||
let min_width = unsafe { arg.min_width.resolve(&mut varargs, &mut ap) };
|
||||
let precision = arg
|
||||
.precision
|
||||
.map(|n| n.resolve(&mut varargs, &mut ap))
|
||||
.map(|n| unsafe { n.resolve(&mut varargs, &mut ap) })
|
||||
.filter(|&n| (n as c_int) >= 0);
|
||||
let pad_zero = if zero { min_width } else { 0 };
|
||||
let signed_space = match pad_zero {
|
||||
@@ -741,7 +746,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
match fmtkind {
|
||||
FmtKind::Percent => w.write_all(&[b'%'])?,
|
||||
FmtKind::Signed => {
|
||||
let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let string = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::c_char(i) => i.to_string(),
|
||||
VaArg::c_double(i) => panic!("this should not be possible"),
|
||||
VaArg::c_int(i) => i.to_string(),
|
||||
@@ -789,7 +796,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
pad(w, left, b' ', final_len..pad_space)?;
|
||||
}
|
||||
FmtKind::Unsigned => {
|
||||
let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let string = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::c_char(i) => fmt_int::<_, T>(fmt, i as c_uchar),
|
||||
VaArg::c_double(i) => panic!("this should not be possible"),
|
||||
VaArg::c_int(i) => fmt_int::<_, T>(fmt, i as c_uint),
|
||||
@@ -848,7 +857,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
pad(w, left, b' ', final_len..pad_space)?;
|
||||
}
|
||||
FmtKind::Scientific => {
|
||||
let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let float = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::c_double(i) => i,
|
||||
_ => panic!("this should not be possible"),
|
||||
};
|
||||
@@ -864,7 +875,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
}
|
||||
}
|
||||
FmtKind::Decimal => {
|
||||
let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let float = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::c_double(i) => i,
|
||||
_ => panic!("this should not be possible"),
|
||||
};
|
||||
@@ -877,7 +890,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
}
|
||||
}
|
||||
FmtKind::AnyNotation => {
|
||||
let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let float = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::c_double(i) => i,
|
||||
_ => panic!("this should not be possible"),
|
||||
};
|
||||
@@ -909,7 +924,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
}
|
||||
}
|
||||
FmtKind::String => {
|
||||
let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let ptr = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::pointer(p) => p,
|
||||
_ => panic!("this should not be possible"),
|
||||
} as *const c_char;
|
||||
@@ -924,8 +941,8 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
let mut ptr = ptr as *const wchar_t;
|
||||
let mut string = String::new();
|
||||
|
||||
while *ptr != 0 {
|
||||
let c = match char::from_u32(*ptr as _) {
|
||||
while unsafe { *ptr } != 0 {
|
||||
let c = match char::from_u32(unsafe { *ptr } as _) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
platform::ERRNO.set(EILSEQ);
|
||||
@@ -936,7 +953,7 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
break;
|
||||
}
|
||||
string.push(c);
|
||||
ptr = ptr.add(1);
|
||||
ptr = unsafe { ptr.add(1) };
|
||||
}
|
||||
|
||||
pad(w, !left, b' ', string.len()..pad_space)?;
|
||||
@@ -944,40 +961,44 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
pad(w, left, b' ', string.len()..pad_space)?;
|
||||
} else {
|
||||
let mut len = 0;
|
||||
while *ptr.add(len) != 0 && len < max {
|
||||
while unsafe { *ptr.add(len) } != 0 && len < max {
|
||||
len += 1;
|
||||
}
|
||||
|
||||
pad(w, !left, b' ', len..pad_space)?;
|
||||
w.write_all(slice::from_raw_parts(ptr as *const u8, len))?;
|
||||
w.write_all(unsafe { slice::from_raw_parts(ptr as *const u8, len) })?;
|
||||
pad(w, left, b' ', len..pad_space)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
FmtKind::Char => match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
VaArg::c_char(c) => {
|
||||
pad(w, !left, b' ', 1..pad_space)?;
|
||||
w.write_all(&[c as u8])?;
|
||||
pad(w, left, b' ', 1..pad_space)?;
|
||||
}
|
||||
VaArg::wint_t(c) => {
|
||||
let c = match char::from_u32(c as _) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
platform::ERRNO.set(EILSEQ);
|
||||
return Err(io::last_os_error());
|
||||
}
|
||||
};
|
||||
let mut buf = [0; 4];
|
||||
FmtKind::Char => {
|
||||
match unsafe { varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) } {
|
||||
VaArg::c_char(c) => {
|
||||
pad(w, !left, b' ', 1..pad_space)?;
|
||||
w.write_all(&[c as u8])?;
|
||||
pad(w, left, b' ', 1..pad_space)?;
|
||||
}
|
||||
VaArg::wint_t(c) => {
|
||||
let c = match char::from_u32(c as _) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
platform::ERRNO.set(EILSEQ);
|
||||
return Err(io::last_os_error());
|
||||
}
|
||||
};
|
||||
let mut buf = [0; 4];
|
||||
|
||||
pad(w, !left, b' ', 1..pad_space)?;
|
||||
w.write_all(c.encode_utf8(&mut buf).as_bytes())?;
|
||||
pad(w, left, b' ', 1..pad_space)?;
|
||||
pad(w, !left, b' ', 1..pad_space)?;
|
||||
w.write_all(c.encode_utf8(&mut buf).as_bytes())?;
|
||||
pad(w, left, b' ', 1..pad_space)?;
|
||||
}
|
||||
_ => unreachable!("this should not be possible"),
|
||||
}
|
||||
_ => unreachable!("this should not be possible"),
|
||||
},
|
||||
}
|
||||
FmtKind::Pointer => {
|
||||
let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let ptr = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::pointer(p) => p,
|
||||
_ => panic!("this should not be possible"),
|
||||
};
|
||||
@@ -1002,20 +1023,26 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
pad(w, left, b' ', len..pad_space)?;
|
||||
}
|
||||
FmtKind::GetWritten => {
|
||||
let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
|
||||
let ptr = match unsafe {
|
||||
varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind)))
|
||||
} {
|
||||
VaArg::pointer(p) => p,
|
||||
_ => panic!("this should not be possible"),
|
||||
};
|
||||
|
||||
match intkind {
|
||||
IntKind::Byte => *(ptr as *mut c_char) = w.written as c_char,
|
||||
IntKind::Short => *(ptr as *mut c_short) = w.written as c_short,
|
||||
IntKind::Int => *(ptr as *mut c_int) = w.written as c_int,
|
||||
IntKind::Long => *(ptr as *mut c_long) = w.written as c_long,
|
||||
IntKind::LongLong => *(ptr as *mut c_longlong) = w.written as c_longlong,
|
||||
IntKind::IntMax => *(ptr as *mut intmax_t) = w.written as intmax_t,
|
||||
IntKind::PtrDiff => *(ptr as *mut ptrdiff_t) = w.written as ptrdiff_t,
|
||||
IntKind::Size => *(ptr as *mut size_t) = w.written as size_t,
|
||||
IntKind::Byte => unsafe { *(ptr as *mut c_char) = w.written as c_char },
|
||||
IntKind::Short => unsafe { *(ptr as *mut c_short) = w.written as c_short },
|
||||
IntKind::Int => unsafe { *(ptr as *mut c_int) = w.written as c_int },
|
||||
IntKind::Long => unsafe { *(ptr as *mut c_long) = w.written as c_long },
|
||||
IntKind::LongLong => unsafe {
|
||||
*(ptr as *mut c_longlong) = w.written as c_longlong
|
||||
},
|
||||
IntKind::IntMax => unsafe { *(ptr as *mut intmax_t) = w.written as intmax_t },
|
||||
IntKind::PtrDiff => unsafe {
|
||||
*(ptr as *mut ptrdiff_t) = w.written as ptrdiff_t
|
||||
},
|
||||
IntKind::Size => unsafe { *(ptr as *mut size_t) = w.written as size_t },
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1292,5 +1319,5 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
|
||||
/// Behavior is undefined if any of the following conditions are violated:
|
||||
/// - `ap` must follow the safety contract of variable arguments of C.
|
||||
pub unsafe fn printf(w: impl Write, format: CStr, ap: VaList) -> c_int {
|
||||
inner_printf::<c_str::Thin>(w, format, ap).unwrap_or(-1)
|
||||
unsafe { inner_printf::<c_str::Thin>(w, format, ap).unwrap_or(-1) }
|
||||
}
|
||||
|
||||
+38
-26
@@ -17,8 +17,8 @@ enum IntKind {
|
||||
|
||||
/// Helper function for progressing a C string
|
||||
unsafe fn next_byte(string: &mut *const c_char) -> Result<u8, c_int> {
|
||||
let c = **string as u8;
|
||||
*string = string.offset(1);
|
||||
let c = unsafe { **string } as u8;
|
||||
*string = unsafe { string.offset(1) };
|
||||
if c == 0 { Err(-1) } else { Ok(c) }
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
}
|
||||
|
||||
while *format != 0 {
|
||||
let mut c = next_byte(&mut format)?;
|
||||
while unsafe { *format } != 0 {
|
||||
let mut c = unsafe { next_byte(&mut format) }?;
|
||||
|
||||
if c == b' ' {
|
||||
maybe_read!(noreset);
|
||||
@@ -87,18 +87,18 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
r.commit();
|
||||
} else {
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
|
||||
let mut ignore = false;
|
||||
if c == b'*' {
|
||||
ignore = true;
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
}
|
||||
|
||||
let mut width = String::new();
|
||||
while c >= b'0' && c <= b'9' {
|
||||
width.push(c as char);
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
}
|
||||
let mut width = if width.is_empty() {
|
||||
None
|
||||
@@ -137,7 +137,7 @@ unsafe fn inner_scanf(
|
||||
_ => break,
|
||||
};
|
||||
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
}
|
||||
|
||||
if c != b'n' {
|
||||
@@ -231,7 +231,7 @@ unsafe fn inner_scanf(
|
||||
n.parse::<$type>().map_err(|_| 0)?
|
||||
};
|
||||
if !ignore {
|
||||
*ap.arg::<*mut $type>() = n;
|
||||
unsafe { *ap.arg::<*mut $type>() = n };
|
||||
matched += 1;
|
||||
}
|
||||
}};
|
||||
@@ -251,7 +251,7 @@ unsafe fn inner_scanf(
|
||||
$type::from_str_radix(&n, radix).map_err(|_| 0)?
|
||||
};
|
||||
if !ignore {
|
||||
*ap.arg::<*mut $final>() = n as $final;
|
||||
unsafe { *ap.arg::<*mut $final>() = n as $final};
|
||||
matched += 1;
|
||||
}
|
||||
}};
|
||||
@@ -329,12 +329,16 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
}
|
||||
|
||||
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
|
||||
let mut ptr: Option<*mut c_char> = if ignore {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { ap.arg() })
|
||||
};
|
||||
|
||||
while width.map(|w| w > 0).unwrap_or(true) && !(byte as char).is_whitespace() {
|
||||
if let Some(ref mut ptr) = ptr {
|
||||
**ptr = byte as c_char;
|
||||
*ptr = ptr.offset(1);
|
||||
unsafe { **ptr = byte as c_char };
|
||||
*ptr = unsafe { ptr.offset(1) };
|
||||
}
|
||||
width = width.map(|w| w - 1);
|
||||
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
|
||||
@@ -344,17 +348,21 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
|
||||
if let Some(ptr) = ptr {
|
||||
*ptr = 0;
|
||||
unsafe { *ptr = 0 };
|
||||
matched += 1;
|
||||
r.commit();
|
||||
}
|
||||
}
|
||||
b'c' => {
|
||||
let ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
|
||||
let ptr: Option<*mut c_char> = if ignore {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { ap.arg() })
|
||||
};
|
||||
|
||||
for i in 0..width.unwrap_or(1) {
|
||||
if let Some(ptr) = ptr {
|
||||
*ptr.add(i) = byte as c_char;
|
||||
unsafe { *ptr.add(i) = byte as c_char };
|
||||
}
|
||||
width = width.map(|w| w - 1);
|
||||
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
|
||||
@@ -369,11 +377,11 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
}
|
||||
b'[' => {
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
|
||||
let mut matches = Vec::new();
|
||||
let invert = if c == b'^' {
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@@ -383,12 +391,12 @@ unsafe fn inner_scanf(
|
||||
loop {
|
||||
matches.push(c);
|
||||
prev = c;
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
if c == b'-' {
|
||||
if prev == b']' {
|
||||
continue;
|
||||
}
|
||||
c = next_byte(&mut format)?;
|
||||
c = unsafe { next_byte(&mut format) }?;
|
||||
if c == b']' {
|
||||
matches.push(b'-');
|
||||
break;
|
||||
@@ -403,15 +411,19 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
}
|
||||
|
||||
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
|
||||
let mut ptr: Option<*mut c_char> = if ignore {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { ap.arg() })
|
||||
};
|
||||
|
||||
// While we haven't used up all the width, and it matches
|
||||
let mut data_stored = false;
|
||||
while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte)
|
||||
{
|
||||
if let Some(ref mut ptr) = ptr {
|
||||
**ptr = byte as c_char;
|
||||
*ptr = ptr.offset(1);
|
||||
unsafe { **ptr = byte as c_char };
|
||||
*ptr = unsafe { ptr.offset(1) };
|
||||
data_stored = true;
|
||||
}
|
||||
r.commit();
|
||||
@@ -426,13 +438,13 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
|
||||
if data_stored {
|
||||
*ptr.unwrap() = 0;
|
||||
unsafe { *ptr.unwrap() = 0 };
|
||||
matched += 1;
|
||||
}
|
||||
}
|
||||
b'n' => {
|
||||
if !ignore {
|
||||
*ap.arg::<*mut c_int>() = count as c_int;
|
||||
unsafe { *ap.arg::<*mut c_int>() = count as c_int };
|
||||
}
|
||||
}
|
||||
_ => return Err(-1),
|
||||
@@ -453,7 +465,7 @@ unsafe fn inner_scanf(
|
||||
}
|
||||
|
||||
pub unsafe fn scanf(r: LookAheadReader, format: *const c_char, ap: va_list) -> c_int {
|
||||
match inner_scanf(r, format, ap) {
|
||||
match unsafe { inner_scanf(r, format, ap) } {
|
||||
Ok(n) => n,
|
||||
Err(n) => n,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user