diff --git a/src/header/time/mod.rs b/src/header/time/mod.rs index 1fe2ba0c40..b2d8417522 100644 --- a/src/header/time/mod.rs +++ b/src/header/time/mod.rs @@ -34,7 +34,7 @@ pub use self::constants::*; pub mod constants; -mod strftime; +pub mod strftime; mod strptime; pub use strptime::strptime; diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index ccbfe1bf5a..465e05ac93 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -2,6 +2,7 @@ //! //! See . +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 . +/// +/// # 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::(), + 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 .