1 /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
2  *
3  * GNU Library General Public License (LGPL) version 2 or later.
4  *
5  * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
6  */
7 
8 #include "_stdio.h"
9 #include <wchar.h>
10 
11 #ifndef __UCLIBC_HAS_WCHAR__
12 #error wide function when no wide support!
13 #endif
14 
15 #ifdef __UCLIBC_MJN3_ONLY__
16 #warning TODO: Fix prototype.
17 #endif
18 
19 
_wstdio_fwrite(const wchar_t * __restrict ws,size_t n,register FILE * __restrict stream)20 size_t attribute_hidden _wstdio_fwrite(const wchar_t *__restrict ws, size_t n,
21 					  register FILE *__restrict stream)
22 {
23 	size_t r, count;
24 	char buf[64];
25 	const wchar_t *pw;
26 
27 	__STDIO_STREAM_VALIDATE(stream);
28 
29 #ifdef __STDIO_BUFFERS
30 	if (__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream)) {
31 		/* We know buffer is wchar aligned for fake streams. */
32 		count = (((wchar_t *)(stream->__bufend))
33 				 - ((wchar_t *)(stream->__bufpos)));
34 		if (count > n) {
35 			count = n;
36 		}
37 		if (count) {
38 			wmemcpy((wchar_t *)(stream->__bufpos), ws, count);
39 			stream->__bufpos = (unsigned char *)(((wchar_t *)(stream->__bufpos)) + count);
40 		}
41 		__STDIO_STREAM_VALIDATE(stream);
42 		return n;
43 	}
44 #endif
45 
46 	count = 0;
47 
48 	if (__STDIO_STREAM_IS_WIDE_WRITING(stream)
49 		|| !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE)
50 		) {
51 
52 		pw = ws;
53 		while (n > count) {
54 			r = wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->__state);
55 			if (r != ((size_t) -1)) { /* No encoding errors */
56 				if (!r) {
57 					++r;		  /* 0 is returned when nul is reached. */
58 					pw = ws + count + r; /* pw was set to NULL, so correct. */
59 				}
60 				if (__stdio_fwrite((const unsigned char *)buf, r, stream) == r) {
61 					count = pw - ws;
62 					continue;
63 				}
64 			}
65 			break;
66 		}
67 
68 		/* Note: The count is incorrect if 0 < __stdio_fwrite return < r!!! */
69 	}
70 
71 	__STDIO_STREAM_VALIDATE(stream);
72 	return count;
73 }
74