Add wcpcpy, wcpncpy, wcsdup, wcsnlen, wcsnrtombs
This commit is contained in:
committed by
Jeremy Soller
parent
2c7ec0dc8e
commit
05992b8451
+93
-2
@@ -4,8 +4,8 @@ use core::{char, ffi::VaList as va_list, mem, ptr, slice, usize};
|
||||
|
||||
use crate::{
|
||||
header::{
|
||||
ctype::isspace, errno::{ERANGE, EILSEQ}, stdio::*,
|
||||
stdlib::MB_CUR_MAX, string, time::*, wctype::*,
|
||||
ctype::isspace, errno::{ERANGE, EILSEQ, ENOMEM}, stdio::*,
|
||||
stdlib::{MB_CUR_MAX, MB_LEN_MAX, malloc}, string, time::*, wctype::*,
|
||||
},
|
||||
platform::{self, errno, types::*},
|
||||
};
|
||||
@@ -319,6 +319,23 @@ pub unsafe extern "C" fn vswprintf(
|
||||
-1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcpcpy(
|
||||
d: *mut wchar_t,
|
||||
s: *const wchar_t,
|
||||
) -> *mut wchar_t {
|
||||
return (wcscpy(d, s)).offset(wcslen(s) as isize);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcpncpy(
|
||||
d: *mut wchar_t,
|
||||
s: *const wchar_t,
|
||||
n: size_t,
|
||||
) -> *mut wchar_t {
|
||||
return (wcsncpy(d, s, n)).offset(wcsnlen(s, n) as isize);
|
||||
}
|
||||
|
||||
//widechar to multibyte
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> size_t {
|
||||
@@ -332,6 +349,20 @@ pub unsafe extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t
|
||||
utf8::wcrtomb(s_cpy, wc_cpy, ps)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
|
||||
let l = wcslen(s);
|
||||
|
||||
let mut d = malloc((l + 1)*mem::size_of::<wchar_t>()) as *mut wchar_t;
|
||||
|
||||
if d.is_null() {
|
||||
errno = ENOMEM;
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
wmemcpy(d, s, l + 1)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcsrtombs(
|
||||
mut s: *mut c_char,
|
||||
@@ -550,6 +581,66 @@ pub unsafe extern "C" fn wcsncpy(
|
||||
ws1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcsnlen(mut s: *const wchar_t, maxlen: size_t) -> size_t {
|
||||
let mut len = 0;
|
||||
|
||||
while len < maxlen {
|
||||
if *s == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
len = len + 1;
|
||||
s = s.offset(1);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcsnrtombs(
|
||||
mut dest: *mut c_char,
|
||||
src: *mut *const wchar_t,
|
||||
nwc: size_t,
|
||||
len: size_t,
|
||||
ps: *mut mbstate_t,
|
||||
) -> size_t {
|
||||
let mut written = 0;
|
||||
let mut read = 0;
|
||||
let mut buf: [c_char; MB_LEN_MAX as usize] = [0; MB_LEN_MAX as usize];
|
||||
|
||||
while read < nwc {
|
||||
buf.fill(0);
|
||||
|
||||
let ret = wcrtomb(buf.as_mut_ptr(), **src, ps);
|
||||
|
||||
if ret == size_t::MAX {
|
||||
errno = EILSEQ;
|
||||
return size_t::MAX;
|
||||
}
|
||||
|
||||
if !dest.is_null() && len < written + ret {
|
||||
return written;
|
||||
}
|
||||
|
||||
if !dest.is_null() {
|
||||
ptr::copy_nonoverlapping(buf.as_ptr(), dest, ret);
|
||||
dest = dest.add(ret);
|
||||
}
|
||||
|
||||
if **src == '\0' as wchar_t {
|
||||
*src = ptr::null();
|
||||
return written;
|
||||
}
|
||||
|
||||
*src = (*src).add(1);
|
||||
read += 1;
|
||||
written += ret;
|
||||
}
|
||||
written
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wcspbrk(mut wcs: *const wchar_t, set: *const wchar_t) -> *mut wchar_t {
|
||||
wcs = wcs.add(wcscspn(wcs, set));
|
||||
|
||||
@@ -111,7 +111,10 @@ EXPECT_NAMES=\
|
||||
wchar/ungetwc \
|
||||
wchar/wprintf \
|
||||
wchar/wcrtomb \
|
||||
wchar/wcpcpy \
|
||||
wchar/wcpncpy \
|
||||
wchar/wcscspn \
|
||||
wchar/wcsdup \
|
||||
wchar/wcsrchr \
|
||||
wchar/wcsrtombs \
|
||||
wchar/wcsstr \
|
||||
@@ -122,6 +125,8 @@ EXPECT_NAMES=\
|
||||
wchar/wcstoumax \
|
||||
wchar/wcscasecmp \
|
||||
wchar/wcsncasecmp \
|
||||
wchar/wcsnlen \
|
||||
wchar/wcsnrtombs \
|
||||
wchar/wcswidth \
|
||||
wctype/towlower \
|
||||
wctype/towupper
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <wchar.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
wchar_t src[] = L"こんにちは世界!";
|
||||
wchar_t dest[9];
|
||||
|
||||
wchar_t* result = wcpcpy(dest, src);
|
||||
|
||||
assert(wcscmp(dest, src) == 0);
|
||||
assert(*result == L'\0');
|
||||
assert(result == dest + wcslen(src));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <wchar.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
wchar_t src[] = L"Привет мир";
|
||||
wchar_t dest[10];
|
||||
wchar_t* result = wcpncpy(dest, src, 5);
|
||||
|
||||
assert(wcsncmp(dest, src, 5) == 0);
|
||||
assert(*result == L'\0');
|
||||
assert(result == dest + 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <wchar.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
wchar_t src[] = L"こんにちは世界Привет мир";
|
||||
|
||||
wchar_t* dup = wcsdup(src);
|
||||
|
||||
assert(wcscmp(dup, src) == 0);
|
||||
assert(dup != src);
|
||||
free(dup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <wchar.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
// size is 17
|
||||
wchar_t* str1 = L"こんにちは世界Привет мир";
|
||||
assert(wcsnlen(str1, 10) == 10);
|
||||
assert(wcsnlen(str1, 100) == 17);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
const wchar_t *src = L"こんにちは世界Привет мир";
|
||||
char dst[20];
|
||||
mbstate_t ps;
|
||||
|
||||
size_t result = wcsnrtombs(dst, &src, 4, sizeof(dst), &ps);
|
||||
assert(result == 12);
|
||||
assert(strcmp(dst, "こんにち") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user