libc: implement wcrtomb()

This commit is contained in:
Mark Poliakov 2024-11-30 12:27:07 +02:00
parent cd22da9098
commit d2a31ef99b

View File

@ -1,20 +1,41 @@
use core::{ffi::{c_char, c_int}, ptr::NonNull};
use core::{
ffi::{c_char, c_int},
ptr::NonNull,
};
use crate::{error::CUsizeResult, headers::wchar::imp, types::wchar_t};
use crate::{
error::{CIntZeroResult, CUsizeResult, OptionExt},
headers::{errno::Errno, stdlib::MB_CUR_MAX, wchar::imp},
types::wchar_t,
util::PointerExt,
};
use super::mbstate_t;
static mut GLOBAL: mbstate_t = mbstate_t { __dummy: 0 };
#[no_mangle]
unsafe extern "C" fn mbrlen(_str: *const c_char, _n: usize, _state: *mut mbstate_t) -> usize {
todo!()
}
#[no_mangle]
unsafe extern "C" fn wcrtomb(_dst: *mut c_char, _wc: wchar_t, _state: *mut mbstate_t) -> usize {
todo!()
unsafe extern "C" fn wcrtomb(dst: *mut c_char, wc: wchar_t, state: *mut mbstate_t) -> CUsizeResult {
let state = match state.as_mut() {
Some(state) => state,
#[allow(static_mut_refs)]
None => &mut GLOBAL,
};
// dst must be at least MB_CUR_MAX (4)
let dst = dst.cast::<u8>().ensure_slice_mut(MB_CUR_MAX as usize);
// TODO EILSEQ
let ch = char::from_u32(wc as u32).e_ok_or(Errno::EINVAL)?;
let len = ch.encode_utf8(dst).len();
CUsizeResult::success(len)
}
#[allow(static_mut_refs)]
#[no_mangle]
pub unsafe extern "C" fn mbrtowc(
dst: *mut wchar_t,
@ -22,17 +43,14 @@ pub unsafe extern "C" fn mbrtowc(
n: usize,
state: *mut mbstate_t,
) -> CUsizeResult {
static mut GLOBAL: mbstate_t = mbstate_t { __dummy: 0 };
let state = match state.as_mut() {
Some(state) => state,
None => &mut GLOBAL
#[allow(static_mut_refs)]
None => &mut GLOBAL,
};
let res = match NonNull::new(src.cast_mut()) {
Some(src) => {
imp::mbrtowc(dst, src, n, state)?
}
Some(src) => imp::mbrtowc(dst, src, n, state)?,
None => {
let x: [c_char; 1] = [0];
imp::mbrtowc(dst, NonNull::from_ref(&x[0]), 1, state)?
@ -43,8 +61,8 @@ pub unsafe extern "C" fn mbrtowc(
}
#[no_mangle]
unsafe extern "C" fn mbsinit(_state: *const mbstate_t) -> c_int {
todo!()
unsafe extern "C" fn mbsinit(_state: *const mbstate_t) -> CIntZeroResult {
CIntZeroResult::SUCCESS
}
#[no_mangle]