mod.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. //! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html
  2. use core::{char, ffi::VaList as va_list, mem, ptr, slice, usize};
  3. use crate::{
  4. header::{
  5. ctype::isspace, errno::ERANGE, stdio::*, stdlib::MB_CUR_MAX, string, time::*, wctype::*,
  6. },
  7. platform::{self, types::*},
  8. };
  9. mod utf8;
  10. #[repr(C)]
  11. #[derive(Clone, Copy)]
  12. pub struct mbstate_t;
  13. #[no_mangle]
  14. pub unsafe extern "C" fn btowc(c: c_int) -> wint_t {
  15. //Check for EOF
  16. if c == EOF {
  17. return WEOF;
  18. }
  19. let uc = c as u8;
  20. let c = uc as c_char;
  21. let mut ps: mbstate_t = mbstate_t;
  22. let mut wc: wchar_t = 0;
  23. let saved_errno = platform::errno;
  24. let status = mbrtowc(&mut wc, &c as *const c_char, 1, &mut ps);
  25. if status == usize::max_value() || status == usize::max_value() - 1 {
  26. platform::errno = saved_errno;
  27. return WEOF;
  28. }
  29. wc as wint_t
  30. }
  31. #[no_mangle]
  32. pub unsafe extern "C" fn fgetwc(stream: *mut FILE) -> wint_t {
  33. //TODO: Real multibyte
  34. btowc(fgetc(stream))
  35. }
  36. #[no_mangle]
  37. pub unsafe extern "C" fn fgetws(ws: *mut wchar_t, n: c_int, stream: *mut FILE) -> *mut wchar_t {
  38. //TODO: lock
  39. let mut i = 0;
  40. while ((i + 1) as c_int) < n {
  41. let wc = fgetwc(stream);
  42. if wc == WEOF {
  43. return ptr::null_mut();
  44. }
  45. *ws.add(i) = wc as wchar_t;
  46. i += 1;
  47. }
  48. while (i as c_int) < n {
  49. *ws.add(i) = 0;
  50. i += 1;
  51. }
  52. ws
  53. }
  54. #[no_mangle]
  55. pub unsafe extern "C" fn fputwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
  56. //Convert wchar_t to multibytes first
  57. static mut INTERNAL: mbstate_t = mbstate_t;
  58. let mut bytes: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize];
  59. let amount = wcrtomb(bytes.as_mut_ptr(), wc, &mut INTERNAL);
  60. for i in 0..amount {
  61. fputc(bytes[i] as c_int, &mut *stream);
  62. }
  63. wc as wint_t
  64. }
  65. #[no_mangle]
  66. pub unsafe extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE) -> c_int {
  67. let mut i = 0;
  68. loop {
  69. let wc = *ws.add(i);
  70. if wc == 0 {
  71. return 0;
  72. }
  73. if fputwc(wc, stream) == WEOF {
  74. return -1;
  75. }
  76. i += 1;
  77. }
  78. }
  79. // #[no_mangle]
  80. pub extern "C" fn fwide(stream: *mut FILE, mode: c_int) -> c_int {
  81. unimplemented!();
  82. }
  83. #[no_mangle]
  84. pub unsafe extern "C" fn getwc(stream: *mut FILE) -> wint_t {
  85. fgetwc(stream)
  86. }
  87. #[no_mangle]
  88. pub unsafe extern "C" fn getwchar() -> wint_t {
  89. fgetwc(stdin)
  90. }
  91. #[no_mangle]
  92. pub unsafe extern "C" fn mbsinit(ps: *const mbstate_t) -> c_int {
  93. //Add a check for the state maybe
  94. if ps.is_null() {
  95. 1
  96. } else {
  97. 0
  98. }
  99. }
  100. #[no_mangle]
  101. pub unsafe extern "C" fn mbrlen(s: *const c_char, n: size_t, ps: *mut mbstate_t) -> size_t {
  102. static mut INTERNAL: mbstate_t = mbstate_t;
  103. mbrtowc(ptr::null_mut(), s, n, &mut INTERNAL)
  104. }
  105. //Only works for UTF8 at the moment
  106. #[no_mangle]
  107. pub unsafe extern "C" fn mbrtowc(
  108. pwc: *mut wchar_t,
  109. s: *const c_char,
  110. n: size_t,
  111. ps: *mut mbstate_t,
  112. ) -> size_t {
  113. static mut INTERNAL: mbstate_t = mbstate_t;
  114. if ps.is_null() {
  115. let ps = &mut INTERNAL;
  116. }
  117. if s.is_null() {
  118. let xs: [c_char; 1] = [0];
  119. utf8::mbrtowc(pwc, &xs[0] as *const c_char, 1, ps)
  120. } else {
  121. utf8::mbrtowc(pwc, s, n, ps)
  122. }
  123. }
  124. //Convert a multibyte string to a wide string with a limited amount of bytes
  125. //Required for in POSIX.1-2008
  126. #[no_mangle]
  127. pub unsafe extern "C" fn mbsnrtowcs(
  128. dst_ptr: *mut wchar_t,
  129. src_ptr: *mut *const c_char,
  130. src_len: size_t,
  131. dst_len: size_t,
  132. ps: *mut mbstate_t,
  133. ) -> size_t {
  134. static mut INTERNAL: mbstate_t = mbstate_t;
  135. if ps.is_null() {
  136. let ps = &mut INTERNAL;
  137. }
  138. let mut src = *src_ptr;
  139. let mut dst_offset: usize = 0;
  140. let mut src_offset: usize = 0;
  141. while (dst_ptr.is_null() || dst_offset < dst_len) && src_offset < src_len {
  142. let ps_copy = *ps;
  143. let mut wc: wchar_t = 0;
  144. let amount = mbrtowc(&mut wc, src.add(src_offset), src_len - src_offset, ps);
  145. // Stop in the event a decoding error occured.
  146. if amount == -1isize as usize {
  147. *src_ptr = src.add(src_offset);
  148. return 1isize as usize;
  149. }
  150. // Stop decoding early in the event we encountered a partial character.
  151. if amount == -2isize as usize {
  152. *ps = ps_copy;
  153. break;
  154. }
  155. // Store the decoded wide character in the destination buffer.
  156. if !dst_ptr.is_null() {
  157. *dst_ptr.add(dst_offset) = wc;
  158. }
  159. // Stop decoding after decoding a null character and return a NULL
  160. // source pointer to the caller, not including the null character in the
  161. // number of characters stored in the destination buffer.
  162. if wc == 0 {
  163. src = ptr::null();
  164. src_offset = 0;
  165. break;
  166. }
  167. dst_offset += 1;
  168. src_offset += amount;
  169. }
  170. *src_ptr = src.add(src_offset);
  171. dst_offset
  172. }
  173. //Convert a multibyte string to a wide string
  174. #[no_mangle]
  175. pub unsafe extern "C" fn mbsrtowcs(
  176. dst: *mut wchar_t,
  177. src: *mut *const c_char,
  178. len: size_t,
  179. ps: *mut mbstate_t,
  180. ) -> size_t {
  181. mbsnrtowcs(dst, src, size_t::max_value(), len, ps)
  182. }
  183. #[no_mangle]
  184. pub unsafe extern "C" fn putwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
  185. fputwc(wc, &mut *stream)
  186. }
  187. #[no_mangle]
  188. pub unsafe extern "C" fn putwchar(wc: wchar_t) -> wint_t {
  189. fputwc(wc, &mut *stdout)
  190. }
  191. // #[no_mangle]
  192. pub extern "C" fn swprintf(
  193. s: *mut wchar_t,
  194. n: size_t,
  195. format: *const wchar_t,
  196. ap: va_list,
  197. ) -> c_int {
  198. unimplemented!();
  199. }
  200. // #[no_mangle]
  201. pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, ap: va_list) -> c_int {
  202. unimplemented!();
  203. }
  204. // #[no_mangle]
  205. pub extern "C" fn ungetwc(wc: wint_t, stream: *mut FILE) -> wint_t {
  206. unimplemented!();
  207. }
  208. // #[no_mangle]
  209. pub extern "C" fn vfwprintf(stream: *mut FILE, format: *const wchar_t, arg: va_list) -> c_int {
  210. unimplemented!();
  211. }
  212. // #[no_mangle]
  213. pub extern "C" fn vwprintf(format: *const wchar_t, arg: va_list) -> c_int {
  214. unimplemented!();
  215. }
  216. // #[no_mangle]
  217. pub extern "C" fn vswprintf(
  218. s: *mut wchar_t,
  219. n: size_t,
  220. format: *const wchar_t,
  221. arg: va_list,
  222. ) -> c_int {
  223. unimplemented!();
  224. }
  225. //widechar to multibyte
  226. #[no_mangle]
  227. pub unsafe extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> size_t {
  228. let mut buffer: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize];
  229. let (s_cpy, wc_cpy) = if s.is_null() {
  230. (buffer.as_mut_ptr(), 0)
  231. } else {
  232. (s, wc)
  233. };
  234. utf8::wcrtomb(s_cpy, wc_cpy, ps)
  235. }
  236. #[no_mangle]
  237. pub unsafe extern "C" fn wcscat(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  238. wcsncat(ws1, ws2, usize::MAX)
  239. }
  240. #[no_mangle]
  241. pub unsafe extern "C" fn wcschr(ws: *const wchar_t, wc: wchar_t) -> *mut wchar_t {
  242. let mut i = 0;
  243. loop {
  244. if *ws.add(i) == wc {
  245. return ws.add(i) as *mut wchar_t;
  246. } else if *ws.add(i) == 0 {
  247. return ptr::null_mut();
  248. }
  249. i += 1;
  250. }
  251. }
  252. #[no_mangle]
  253. pub unsafe extern "C" fn wcscmp(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int {
  254. wcsncmp(ws1, ws2, usize::MAX)
  255. }
  256. #[no_mangle]
  257. pub unsafe extern "C" fn wcscoll(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int {
  258. //TODO: locale comparison
  259. wcscmp(ws1, ws2)
  260. }
  261. #[no_mangle]
  262. pub unsafe extern "C" fn wcscpy(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  263. let mut i = 0;
  264. loop {
  265. let wc = *ws2.add(i);
  266. *ws1.add(i) = wc;
  267. i += 1;
  268. if wc == 0 {
  269. return ws1;
  270. }
  271. }
  272. }
  273. unsafe fn inner_wcsspn(mut wcs: *const wchar_t, set: *const wchar_t, reject: bool) -> size_t {
  274. let mut count = 0;
  275. while (*wcs) != 0 && wcschr(set, *wcs).is_null() == reject {
  276. wcs = wcs.add(1);
  277. count += 1;
  278. }
  279. count
  280. }
  281. #[no_mangle]
  282. pub unsafe extern "C" fn wcscspn(wcs: *const wchar_t, set: *const wchar_t) -> size_t {
  283. inner_wcsspn(wcs, set, true)
  284. }
  285. // #[no_mangle]
  286. pub extern "C" fn wcsftime(
  287. wcs: *mut wchar_t,
  288. maxsize: size_t,
  289. format: *const wchar_t,
  290. timptr: *mut tm,
  291. ) -> size_t {
  292. unimplemented!();
  293. }
  294. #[no_mangle]
  295. pub unsafe extern "C" fn wcslen(ws: *const wchar_t) -> size_t {
  296. let mut i = 0;
  297. loop {
  298. if *ws.add(i) == 0 {
  299. return i;
  300. }
  301. i += 1;
  302. }
  303. }
  304. #[no_mangle]
  305. pub unsafe extern "C" fn wcsncat(
  306. ws1: *mut wchar_t,
  307. ws2: *const wchar_t,
  308. n: size_t,
  309. ) -> *mut wchar_t {
  310. let len = wcslen(ws1);
  311. let dest = ws1.add(len);
  312. let mut i = 0;
  313. while i < n {
  314. let wc = *ws2.add(i);
  315. if wc == 0 {
  316. break;
  317. }
  318. *dest.add(i) = wc;
  319. i += 1;
  320. }
  321. *dest.add(i) = 0;
  322. ws1
  323. }
  324. #[no_mangle]
  325. pub unsafe extern "C" fn wcsncmp(ws1: *const wchar_t, ws2: *const wchar_t, n: size_t) -> c_int {
  326. for i in 0..n {
  327. let wc1 = *ws1.add(i);
  328. let wc2 = *ws2.add(i);
  329. if wc1 != wc2 {
  330. return wc1 - wc2;
  331. } else if wc1 == 0 {
  332. break;
  333. }
  334. }
  335. 0
  336. }
  337. #[no_mangle]
  338. pub unsafe extern "C" fn wcsncpy(
  339. ws1: *mut wchar_t,
  340. ws2: *const wchar_t,
  341. n: size_t,
  342. ) -> *mut wchar_t {
  343. let mut i = 0;
  344. while i < n {
  345. let wc = *ws2.add(i);
  346. *ws1.add(i) = wc;
  347. i += 1;
  348. if wc == 0 {
  349. break;
  350. }
  351. }
  352. while i < n {
  353. *ws1.add(i) = 0;
  354. i += 1;
  355. }
  356. ws1
  357. }
  358. #[no_mangle]
  359. pub unsafe extern "C" fn wcspbrk(mut wcs: *const wchar_t, set: *const wchar_t) -> *mut wchar_t {
  360. wcs = wcs.add(wcscspn(wcs, set));
  361. if *wcs == 0 {
  362. ptr::null_mut()
  363. } else {
  364. // Once again, C wants us to transmute a const pointer to a
  365. // mutable one...
  366. wcs as *mut _
  367. }
  368. }
  369. #[no_mangle]
  370. pub unsafe extern "C" fn wcsrchr(ws1: *const wchar_t, wc: wchar_t) -> *mut wchar_t {
  371. let mut last_matching_wc = 0 as *const wchar_t;
  372. let mut i = 0;
  373. while *ws1.add(i) != 0 {
  374. if *ws1.add(i) == wc {
  375. last_matching_wc = ws1.add(i);
  376. }
  377. i += 1;
  378. }
  379. last_matching_wc as *mut wchar_t
  380. }
  381. // #[no_mangle]
  382. pub extern "C" fn wcsrtombs(
  383. dst: *mut c_char,
  384. src: *mut *const wchar_t,
  385. len: size_t,
  386. ps: *mut mbstate_t,
  387. ) -> size_t {
  388. unimplemented!();
  389. }
  390. #[no_mangle]
  391. pub unsafe extern "C" fn wcsspn(wcs: *const wchar_t, set: *const wchar_t) -> size_t {
  392. inner_wcsspn(wcs, set, false)
  393. }
  394. #[no_mangle]
  395. pub unsafe extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  396. // Get length of ws2, not including null terminator
  397. let ws2_len = wcslen(ws2);
  398. // The standard says that we must return ws1 if ws2 has length 0
  399. if ws2_len == 0 {
  400. ws1 as *mut wchar_t
  401. } else {
  402. let ws1_len = wcslen(ws1);
  403. // Construct slices without null terminator
  404. let ws1_slice = slice::from_raw_parts(ws1, ws1_len);
  405. let ws2_slice = slice::from_raw_parts(ws2, ws2_len);
  406. /* Sliding ws2-sized window iterator on ws1. The iterator
  407. * returns None if ws2 is longer than ws1. */
  408. let mut ws1_windows = ws1_slice.windows(ws2_len);
  409. /* Find the first offset into ws1 where the window is equal to
  410. * the ws2 contents. Return null pointer if no match is found. */
  411. match ws1_windows.position(|ws1_window| ws1_window == ws2_slice) {
  412. Some(pos) => ws1.add(pos) as *mut wchar_t,
  413. None => ptr::null_mut(),
  414. }
  415. }
  416. }
  417. macro_rules! skipws {
  418. ($ptr:expr) => {
  419. while isspace(*$ptr) != 0 {
  420. $ptr = $ptr.add(1);
  421. }
  422. };
  423. }
  424. #[no_mangle]
  425. pub unsafe extern "C" fn wcstod(mut ptr: *const wchar_t, end: *mut *mut wchar_t) -> c_double {
  426. const RADIX: u32 = 10;
  427. skipws!(ptr);
  428. let negative = *ptr == '-' as wchar_t;
  429. if negative {
  430. ptr = ptr.add(1);
  431. }
  432. let mut result: c_double = 0.0;
  433. while let Some(digit) = char::from_u32(*ptr as _).and_then(|c| c.to_digit(RADIX)) {
  434. result *= 10.0;
  435. if negative {
  436. result -= digit as c_double;
  437. } else {
  438. result += digit as c_double;
  439. }
  440. ptr = ptr.add(1);
  441. }
  442. if *ptr == '.' as wchar_t {
  443. ptr = ptr.add(1);
  444. let mut scale = 1.0;
  445. while let Some(digit) = char::from_u32(*ptr as _).and_then(|c| c.to_digit(RADIX)) {
  446. scale /= 10.0;
  447. if negative {
  448. result -= digit as c_double * scale;
  449. } else {
  450. result += digit as c_double * scale;
  451. }
  452. ptr = ptr.add(1);
  453. }
  454. }
  455. if !end.is_null() {
  456. *end = ptr as *mut _;
  457. }
  458. result
  459. }
  460. #[no_mangle]
  461. pub unsafe extern "C" fn wcstok(
  462. mut wcs: *mut wchar_t,
  463. delim: *const wchar_t,
  464. state: *mut *mut wchar_t,
  465. ) -> *mut wchar_t {
  466. // Choose starting position
  467. if wcs.is_null() {
  468. if (*state).is_null() {
  469. // There was no next token
  470. return ptr::null_mut();
  471. }
  472. wcs = *state;
  473. }
  474. // Advance past any delimiters
  475. wcs = wcs.add(wcsspn(wcs, delim));
  476. // Check end
  477. if *wcs == 0 {
  478. *state = ptr::null_mut();
  479. return ptr::null_mut();
  480. }
  481. // Advance *to* any delimiters
  482. let end = wcspbrk(wcs, delim);
  483. if end.is_null() {
  484. *state = ptr::null_mut();
  485. } else {
  486. *end = 0;
  487. *state = end.add(1);
  488. }
  489. wcs
  490. }
  491. macro_rules! strtou_impl {
  492. ($type:ident, $ptr:expr, $base:expr) => {
  493. strtou_impl!($type, $ptr, $base, false)
  494. };
  495. ($type:ident, $ptr:expr, $base:expr, $negative:expr) => {{
  496. if $base == 16 && *$ptr == '0' as wchar_t && *$ptr.add(1) | 0x20 == 'x' as wchar_t {
  497. $ptr = $ptr.add(2);
  498. }
  499. let mut result: $type = 0;
  500. while let Some(digit) = char::from_u32(*$ptr as u32).and_then(|c| c.to_digit($base as u32))
  501. {
  502. let new = result.checked_mul($base as $type).and_then(|result| {
  503. if $negative {
  504. result.checked_sub(digit as $type)
  505. } else {
  506. result.checked_add(digit as $type)
  507. }
  508. });
  509. result = match new {
  510. Some(new) => new,
  511. None => {
  512. platform::errno = ERANGE;
  513. return !0;
  514. }
  515. };
  516. $ptr = $ptr.add(1);
  517. }
  518. result
  519. }};
  520. }
  521. macro_rules! strto_impl {
  522. ($type:ident, $ptr:expr, $base:expr) => {{
  523. let negative = *$ptr == '-' as wchar_t;
  524. if negative {
  525. $ptr = $ptr.add(1);
  526. }
  527. strtou_impl!($type, $ptr, $base, negative)
  528. }};
  529. }
  530. #[no_mangle]
  531. pub unsafe extern "C" fn wcstol(
  532. mut ptr: *const wchar_t,
  533. end: *mut *mut wchar_t,
  534. base: c_int,
  535. ) -> c_long {
  536. skipws!(ptr);
  537. let result = strto_impl!(c_long, ptr, base);
  538. if !end.is_null() {
  539. *end = ptr as *mut _;
  540. }
  541. result
  542. }
  543. #[no_mangle]
  544. pub unsafe extern "C" fn wcstoul(
  545. mut ptr: *const wchar_t,
  546. end: *mut *mut wchar_t,
  547. base: c_int,
  548. ) -> c_ulong {
  549. skipws!(ptr);
  550. let result = strtou_impl!(c_ulong, ptr, base);
  551. if !end.is_null() {
  552. *end = ptr as *mut _;
  553. }
  554. result
  555. }
  556. // #[no_mangle]
  557. pub extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
  558. unimplemented!();
  559. }
  560. // #[no_mangle]
  561. pub extern "C" fn wcswidth(pwcs: *const wchar_t, n: size_t) -> c_int {
  562. unimplemented!();
  563. }
  564. // #[no_mangle]
  565. pub extern "C" fn wcsxfrm(ws1: *mut wchar_t, ws2: *const wchar_t, n: size_t) -> size_t {
  566. unimplemented!();
  567. }
  568. #[no_mangle]
  569. pub extern "C" fn wctob(c: wint_t) -> c_int {
  570. if c <= 0x7F {
  571. c as c_int
  572. } else {
  573. EOF
  574. }
  575. }
  576. // #[no_mangle]
  577. pub extern "C" fn wcwidth(wc: wchar_t) -> c_int {
  578. unimplemented!();
  579. }
  580. #[no_mangle]
  581. pub unsafe extern "C" fn wmemchr(ws: *const wchar_t, wc: wchar_t, n: size_t) -> *mut wchar_t {
  582. for i in 0..n {
  583. if *ws.add(i) == wc {
  584. return ws.add(i) as *mut wchar_t;
  585. }
  586. }
  587. ptr::null_mut()
  588. }
  589. #[no_mangle]
  590. pub unsafe extern "C" fn wmemcmp(ws1: *const wchar_t, ws2: *const wchar_t, n: size_t) -> c_int {
  591. for i in 0..n {
  592. let wc1 = *ws1.add(i);
  593. let wc2 = *ws2.add(i);
  594. if wc1 != wc2 {
  595. return wc1 - wc2;
  596. }
  597. }
  598. 0
  599. }
  600. #[no_mangle]
  601. pub unsafe extern "C" fn wmemcpy(
  602. ws1: *mut wchar_t,
  603. ws2: *const wchar_t,
  604. n: size_t,
  605. ) -> *mut wchar_t {
  606. string::memcpy(
  607. ws1 as *mut c_void,
  608. ws2 as *const c_void,
  609. n * mem::size_of::<wchar_t>(),
  610. ) as *mut wchar_t
  611. }
  612. #[no_mangle]
  613. pub unsafe extern "C" fn wmemmove(
  614. ws1: *mut wchar_t,
  615. ws2: *const wchar_t,
  616. n: size_t,
  617. ) -> *mut wchar_t {
  618. string::memmove(
  619. ws1 as *mut c_void,
  620. ws2 as *const c_void,
  621. n * mem::size_of::<wchar_t>(),
  622. ) as *mut wchar_t
  623. }
  624. #[no_mangle]
  625. pub unsafe extern "C" fn wmemset(ws: *mut wchar_t, wc: wchar_t, n: size_t) -> *mut wchar_t {
  626. for i in 0..n {
  627. *ws.add(i) = wc;
  628. }
  629. ws
  630. }
  631. // #[no_mangle]
  632. pub extern "C" fn wprintf(format: *const wchar_t, ap: va_list) -> c_int {
  633. unimplemented!();
  634. }
  635. // #[no_mangle]
  636. pub extern "C" fn wscanf(format: *const wchar_t, ap: va_list) -> c_int {
  637. unimplemented!();
  638. }