]> pd.if.org Git - pdclib.old/blobdiff - functions/stdio/_PDCLIB_flushbuffer.c
flushbuffer: make EOL conversion code more robust against I/O errors
[pdclib.old] / functions / stdio / _PDCLIB_flushbuffer.c
index 7ee0d93c35730aa08b1baaa28128d2e735f23f16..b3357ade950233953a03b74a0a535f63c2816df3 100644 (file)
 #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
+static int flushsubbuffer( FILE * stream, size_t length )\r
+{\r
+    size_t justWrote;\r
     size_t written = 0;\r
+    int rv = 0;\r
+\r
+#if 0\r
+    // Very useful for debugging buffering issues\r
+    char l = '<', r = '>';\r
+    stream->ops->write( stream->handle, &l,  1, &justWrote );\r
+#endif\r
 \r
+    while( written != length )\r
+    {\r
+        size_t toWrite = length - written;\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
+        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
+        if (!res)\r
+        {\r
+            stream->status |= _PDCLIB_ERRORFLAG;\r
+            rv = EOF;\r
+            break;\r
         }\r
     }\r
 \r
-    stream->bufidx = 0;\r
-    return 0;\r
+#if 0\r
+    stream->ops->write( stream->handle, &r,  1, &justWrote );\r
+#endif\r
+\r
+    stream->bufidx   -= written;\r
+#ifdef _PDCLIB_NEED_EOL_TRANSLATION\r
+    stream->bufnlexp -= written;\r
+#endif\r
+    memmove( stream->buffer, stream->buffer + written, stream->bufidx );\r
+\r
+    return rv;\r
+}\r
+\r
+int _PDCLIB_flushbuffer( FILE * stream )\r
+{\r
+#ifdef _PDCLIB_NEED_EOL_TRANSLATION\r
+    // if a text stream, and this platform needs EOL translation, well...\r
+    if ( ! ( stream->status & _PDCLIB_FBIN ) )\r
+    {\r
+        // Special case: buffer is full and we start with a \n\r
+        if ( stream->bufnlexp == 0\r
+            && stream->bufidx == stream->bufend\r
+            && stream->buffer[0] == '\n' )\r
+        {\r
+            char cr = '\r';\r
+            size_t written = 0;\r
+            bool res = stream->ops->write( stream->handle, &cr, 1, &written );\r
+\r
+            if (!res) {\r
+                stream->status |= _PDCLIB_ERRORFLAG;\r
+                return EOF;\r
+            }\r
+\r
+        }\r
+\r
+        for ( ; stream->bufnlexp < stream->bufidx; stream->bufnlexp++ )\r
+        {\r
+            if (stream->buffer[stream->bufnlexp] == '\n' ) {\r
+                if ( stream->bufidx == stream->bufend ) {\r
+                    // buffer is full. Need to print out everything up till now\r
+                    if( flushsubbuffer( stream, stream->bufnlexp - 1 ) )\r
+                    {\r
+                        return EOF;\r
+                    }\r
+                }\r
+\r
+                // we have spare space in buffer. Shift everything 1char and\r
+                // insert \r\r
+                memmove( &stream->buffer[stream->bufnlexp + 1],\r
+                         &stream->buffer[stream->bufnlexp],\r
+                         stream->bufidx - stream->bufnlexp );\r
+                stream->buffer[stream->bufnlexp] = '\r';\r
+\r
+                stream->bufnlexp++;\r
+                stream->bufidx++;\r
+            }\r
+        }\r
+    }\r
+#endif\r
+    return flushsubbuffer( stream, stream->bufidx );\r
 }\r
 \r
 #endif\r