/* 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 libc_hidden_proto(wmemcpy) libc_hidden_proto(wcsnrtombs) size_t attribute_hidden _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; }