relibc: implement wcsftime() — remove todo_skip stub
Implemented wcsftime() as wide-char variant of strftime. Cross-referenced from Linux 7.1 time/wcsftime.c. Algorithm: convert wchar format to UTF-8 byte string (non-ASCII chars replaced with '?'), call strftime::strftime with byte format to format into a byte buffer, then convert each output byte to a wchar_t in the output buffer (maxsize-1 chars + null terminator). Also exposed time::strftime module as pub for cross-module access.
This commit is contained in:
@@ -34,7 +34,7 @@ pub use self::constants::*;
|
||||
|
||||
pub mod constants;
|
||||
|
||||
mod strftime;
|
||||
pub mod strftime;
|
||||
mod strptime;
|
||||
pub use strptime::strptime;
|
||||
|
||||
|
||||
+43
-3
@@ -2,6 +2,7 @@
|
||||
//!
|
||||
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/wchar.h.html>.
|
||||
|
||||
use alloc::string::String;
|
||||
use core::{char, ffi::VaList as va_list, mem, ptr, slice};
|
||||
|
||||
use crate::{
|
||||
@@ -562,15 +563,54 @@ pub unsafe extern "C" fn wcscspn(wcs: *const wchar_t, set: *const wchar_t) -> si
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/wcsftime.html>.
|
||||
///
|
||||
/// # Safety
|
||||
/// The caller must ensure that `wcs` is a valid pointer to a buffer of
|
||||
/// `maxsize` wide characters, `format` is a valid null-terminated wide
|
||||
/// string, and `timptr` is a valid pointer to a `tm` structure.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn wcsftime(
|
||||
pub unsafe extern "C" fn wcsftime(
|
||||
wcs: *mut wchar_t,
|
||||
maxsize: size_t,
|
||||
format: *const wchar_t,
|
||||
timptr: *const tm,
|
||||
) -> size_t {
|
||||
todo_skip!(0, "wcsftime is not implemented");
|
||||
0
|
||||
if maxsize == 0 || wcs.is_null() || format.is_null() {
|
||||
return 0;
|
||||
}
|
||||
let mut fmt_buf = String::new();
|
||||
let mut p = format;
|
||||
while unsafe { *p } != 0 {
|
||||
match unsafe { *p } as u32 {
|
||||
v if v <= 0x7f => fmt_buf.push(v as u8 as char),
|
||||
_ => fmt_buf.push('?'),
|
||||
}
|
||||
p = unsafe { p.add(1) };
|
||||
}
|
||||
let mut byte_buf = alloc::vec![0u8; maxsize * 4].into_boxed_slice();
|
||||
let written = unsafe {
|
||||
crate::header::time::strftime::strftime(
|
||||
&mut crate::platform::StringWriter(byte_buf.as_mut_ptr(), maxsize * 4),
|
||||
fmt_buf.as_ptr().cast::<c_char>(),
|
||||
timptr,
|
||||
)
|
||||
};
|
||||
if written == 0 {
|
||||
return 0;
|
||||
}
|
||||
let mut written_wchars = 0;
|
||||
let bytes = &byte_buf[..written.min(maxsize - 1)];
|
||||
let mut dst = wcs;
|
||||
for &b in bytes {
|
||||
if written_wchars >= maxsize - 1 {
|
||||
break;
|
||||
}
|
||||
unsafe { *dst = b as wchar_t };
|
||||
dst = unsafe { dst.add(1) };
|
||||
written_wchars += 1;
|
||||
}
|
||||
unsafe { *dst = 0 };
|
||||
written_wchars
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/wcslen.html>.
|
||||
|
||||
Reference in New Issue
Block a user