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:
Red Bear OS
2026-07-08 18:14:05 +03:00
parent 01807f6fa7
commit 8d8c9c9bfd
2 changed files with 44 additions and 4 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ pub use self::constants::*;
pub mod constants;
mod strftime;
pub mod strftime;
mod strptime;
pub use strptime::strptime;
+43 -3
View File
@@ -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>.