summaryrefslogtreecommitdiff
path: root/libc/stdio/_wfwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/stdio/_wfwrite.c')
-rw-r--r--libc/stdio/_wfwrite.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/libc/stdio/_wfwrite.c b/libc/stdio/_wfwrite.c
new file mode 100644
index 000000000..8f9469162
--- /dev/null
+++ b/libc/stdio/_wfwrite.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * GNU Library General Public License (LGPL) version 2 or later.
+ *
+ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
+ */
+
+#include "_stdio.h"
+#include <wchar.h>
+
+#ifndef __UCLIBC_HAS_WCHAR__
+#error wide function when no wide support!
+#endif
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Fix prototype.
+#endif
+extern size_t __wcsnrtombs(char *__restrict dst,
+ const wchar_t **__restrict src,
+ size_t NWC, size_t len, mbstate_t *__restrict ps);
+
+size_t _wstdio_fwrite(const wchar_t *__restrict ws, size_t n,
+ register FILE *__restrict stream)
+{
+ size_t r, count;
+ char buf[64];
+ const wchar_t *pw;
+
+ __STDIO_STREAM_VALIDATE(stream);
+
+#ifdef __STDIO_BUFFERS
+ if (__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream)) {
+ /* We know buffer is wchar aligned for fake streams. */
+ count = (((wchar_t *)(stream->__bufend))
+ - ((wchar_t *)(stream->__bufpos)));
+ if (count > n) {
+ count = n;
+ }
+ if (count) {
+ wmemcpy((wchar_t *)(stream->__bufpos), ws, count);
+ stream->__bufpos = (char *)(((wchar_t *)(stream->__bufpos)) + count);
+ }
+ __STDIO_STREAM_VALIDATE(stream);
+ return n;
+ }
+#endif
+
+ count = 0;
+
+ if (__STDIO_STREAM_IS_WIDE_WRITING(stream)
+ || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE)
+ ) {
+
+ pw = ws;
+ while (n > count) {
+ r = __wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->__state);
+ if (r != ((size_t) -1)) { /* No encoding errors */
+ if (!r) {
+ ++r; /* 0 is returned when nul is reached. */
+ pw = ws + count + r; /* pw was set to NULL, so correct. */
+ }
+ if (__stdio_fwrite(buf, r, stream) == r) {
+ count = pw - ws;
+ continue;
+ }
+ }
+ break;
+ }
+
+ /* Note: The count is incorrect if 0 < __stdio_fwrite return < r!!! */
+ }
+
+ __STDIO_STREAM_VALIDATE(stream);
+ return count;
+}