-/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * )\r
-\r
- This file is part of the Public Domain C Library (PDCLib).\r
- Permission is granted to use, modify, and / or redistribute at will.\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#ifndef REGTEST\r
-#include <_PDCLIB_glue.h>\r
-#include <_PDCLIB_io.h>\r
-\r
-int _PDCLIB_flushbuffer( FILE * stream )\r
-{\r
- if ( ! ( stream->status & _PDCLIB_FBIN ) )\r
- {\r
- /* TODO: Text stream conversion here */\r
- }\r
-\r
- size_t written = 0;\r
-\r
-\r
- while(written != stream->bufidx) {\r
- size_t justWrote;\r
- size_t toWrite = stream->bufidx - written;\r
- bool res = stream->ops->write( stream->handle, stream->buffer + written, \r
- toWrite, &justWrote);\r
- written += justWrote;\r
- stream->pos.offset += justWrote;\r
-\r
- if(!res) {\r
- stream->status |=_PDCLIB_ERRORFLAG;\r
- stream->bufidx -= written;\r
- memmove( stream->buffer, stream->buffer + written, stream->bufidx );\r
- return EOF;\r
- }\r
- }\r
-\r
- stream->bufidx = 0;\r
- return 0;\r
-}\r
-\r
-#endif\r
-\r
-\r
-#ifdef TEST\r
-#include <_PDCLIB_test.h>\r
-\r
-int main( void )\r
-{\r
- /* Testing covered by ftell.c */\r
- return TEST_RESULTS;\r
-}\r
-\r
-#endif\r
-\r
+/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * )
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef REGTEST
+#include "_PDCLIB_glue.h"
+#include "_PDCLIB_io.h"
+
+
+static int flushsubbuffer( FILE * stream, size_t length )
+{
+ size_t justWrote;
+ size_t written = 0;
+ int rv = 0;
+
+#if 0
+ // Very useful for debugging buffering issues
+ char l = '<', r = '>';
+ stream->ops->write( stream->handle, &l, 1, &justWrote );
+#endif
+
+ while( written != length )
+ {
+ size_t toWrite = length - written;
+
+ bool res = stream->ops->write( stream->handle, stream->buffer + written,
+ toWrite, &justWrote);
+ written += justWrote;
+ stream->pos.offset += justWrote;
+
+ if (!res)
+ {
+ stream->status |= _PDCLIB_ERRORFLAG;
+ rv = EOF;
+ break;
+ }
+ }
+
+#if 0
+ stream->ops->write( stream->handle, &r, 1, &justWrote );
+#endif
+
+ stream->bufidx -= written;
+#ifdef _PDCLIB_NEED_EOL_TRANSLATION
+ stream->bufnlexp -= written;
+#endif
+ memmove( stream->buffer, stream->buffer + written, stream->bufidx );
+
+ return rv;
+}
+
+int _PDCLIB_flushbuffer( FILE * stream )
+{
+#ifdef _PDCLIB_NEED_EOL_TRANSLATION
+ // if a text stream, and this platform needs EOL translation, well...
+ if ( ! ( stream->status & _PDCLIB_FBIN ) )
+ {
+ // Special case: buffer is full and we start with a \n
+ if ( stream->bufnlexp == 0
+ && stream->bufidx == stream->bufend
+ && stream->buffer[0] == '\n' )
+ {
+ char cr = '\r';
+ size_t written = 0;
+ bool res = stream->ops->write( stream->handle, &cr, 1, &written );
+
+ if (!res) {
+ stream->status |= _PDCLIB_ERRORFLAG;
+ return EOF;
+ }
+
+ }
+
+ for ( ; stream->bufnlexp < stream->bufidx; stream->bufnlexp++ )
+ {
+ if (stream->buffer[stream->bufnlexp] == '\n' ) {
+ if ( stream->bufidx == stream->bufend ) {
+ // buffer is full. Need to print out everything up till now
+ if( flushsubbuffer( stream, stream->bufnlexp - 1 ) )
+ {
+ return EOF;
+ }
+ }
+
+ // we have spare space in buffer. Shift everything 1char and
+ // insert \r
+ memmove( &stream->buffer[stream->bufnlexp + 1],
+ &stream->buffer[stream->bufnlexp],
+ stream->bufidx - stream->bufnlexp );
+ stream->buffer[stream->bufnlexp] = '\r';
+
+ stream->bufnlexp++;
+ stream->bufidx++;
+ }
+ }
+ }
+#endif
+ return flushsubbuffer( stream, stream->bufidx );
+}
+
+#endif
+
+
+#ifdef TEST
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ /* Testing covered by ftell.c */
+ return TEST_RESULTS;
+}
+
+#endif
+