summaryrefslogtreecommitdiff
path: root/libc/stdio/_fwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/stdio/_fwrite.c')
-rw-r--r--libc/stdio/_fwrite.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/libc/stdio/_fwrite.c b/libc/stdio/_fwrite.c
new file mode 100644
index 000000000..a706ba7e6
--- /dev/null
+++ b/libc/stdio/_fwrite.c
@@ -0,0 +1,78 @@
+/* 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"
+
+#ifdef __STDIO_BUFFERS
+
+/* Either buffer data or (commit buffer if necessary and) write. */
+
+size_t __stdio_fwrite(const unsigned char * __restrict buffer,
+ size_t bytes,
+ register FILE * __restrict stream)
+{
+ size_t pending;
+ const unsigned char *p;
+
+ __STDIO_STREAM_VALIDATE(stream);
+ assert(__STDIO_STREAM_IS_WRITING(stream));
+ assert(buffer);
+ assert(bytes);
+
+ if (!__STDIO_STREAM_IS_NBF(stream)) { /* FBF or LBF. */
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Try to consolidate some of the code?
+#endif
+ if (__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)) {
+ pending = __STDIO_STREAM_BUFFER_WAVAIL(stream);
+ if (pending > bytes) {
+ pending = bytes;
+ }
+ memcpy(stream->__bufpos, buffer, pending);
+ stream->__bufpos += pending;
+ __STDIO_STREAM_VALIDATE(stream);
+ return bytes;
+ }
+
+/* RETRY: */
+ if (bytes <= __STDIO_STREAM_BUFFER_WAVAIL(stream)) {
+ memcpy(stream->__bufpos, buffer, bytes);
+ stream->__bufpos += bytes;
+ if (__STDIO_STREAM_IS_LBF(stream)
+ && memrchr(buffer, '\n', bytes) /* Search backwards. */
+ ) {
+ if ((pending = __STDIO_COMMIT_WRITE_BUFFER(stream)) > 0) {
+ if (pending > bytes) {
+ pending = bytes;
+ }
+ buffer += (bytes - pending);
+ if ((p = memchr(buffer, '\n', pending)) != NULL) {
+ pending = (buffer + pending) - p;
+ bytes -= pending;
+ stream->__bufpos -= pending;
+ }
+ }
+ }
+ __STDIO_STREAM_VALIDATE(stream);
+ return bytes;
+ }
+ /* FBF or LBF and not enough space in buffer. */
+ if (__STDIO_STREAM_BUFFER_WUSED(stream)) { /* Buffered data. */
+ if (__STDIO_COMMIT_WRITE_BUFFER(stream)) { /* Commit failed! */
+ return 0;
+ }
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Do we want to try again if data now fits in buffer?
+#endif
+/* goto RETRY; */
+ }
+ }
+
+ return __stdio_WRITE(stream, buffer, bytes);
+}
+
+#endif