]> pd.if.org Git - pdclib.old/blob - functions/stdio/_PDCLIB_flushbuffer.c
flushbuffer: make EOL conversion code more robust against I/O errors
[pdclib.old] / functions / stdio / _PDCLIB_flushbuffer.c
1 /* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * )\r
2 \r
3    This file is part of the Public Domain C Library (PDCLib).\r
4    Permission is granted to use, modify, and / or redistribute at will.\r
5 */\r
6 \r
7 #include <stdio.h>\r
8 #include <string.h>\r
9 \r
10 #ifndef REGTEST\r
11 #include <_PDCLIB_glue.h>\r
12 #include <_PDCLIB_io.h>\r
13 \r
14 \r
15 static int flushsubbuffer( FILE * stream, size_t length )\r
16 {\r
17     size_t justWrote;\r
18     size_t written = 0;\r
19     int rv = 0;\r
20 \r
21 #if 0\r
22     // Very useful for debugging buffering issues\r
23     char l = '<', r = '>';\r
24     stream->ops->write( stream->handle, &l,  1, &justWrote );\r
25 #endif\r
26 \r
27     while( written != length )\r
28     {\r
29         size_t toWrite = length - written;\r
30 \r
31         bool res = stream->ops->write( stream->handle, stream->buffer + written,\r
32                               toWrite, &justWrote);\r
33         written += justWrote;\r
34         stream->pos.offset += justWrote;\r
35 \r
36         if (!res)\r
37         {\r
38             stream->status |= _PDCLIB_ERRORFLAG;\r
39             rv = EOF;\r
40             break;\r
41         }\r
42     }\r
43 \r
44 #if 0\r
45     stream->ops->write( stream->handle, &r,  1, &justWrote );\r
46 #endif\r
47 \r
48     stream->bufidx   -= written;\r
49 #ifdef _PDCLIB_NEED_EOL_TRANSLATION\r
50     stream->bufnlexp -= written;\r
51 #endif\r
52     memmove( stream->buffer, stream->buffer + written, stream->bufidx );\r
53 \r
54     return rv;\r
55 }\r
56 \r
57 int _PDCLIB_flushbuffer( FILE * stream )\r
58 {\r
59 #ifdef _PDCLIB_NEED_EOL_TRANSLATION\r
60     // if a text stream, and this platform needs EOL translation, well...\r
61     if ( ! ( stream->status & _PDCLIB_FBIN ) )\r
62     {\r
63         // Special case: buffer is full and we start with a \n\r
64         if ( stream->bufnlexp == 0\r
65             && stream->bufidx == stream->bufend\r
66             && stream->buffer[0] == '\n' )\r
67         {\r
68             char cr = '\r';\r
69             size_t written = 0;\r
70             bool res = stream->ops->write( stream->handle, &cr, 1, &written );\r
71 \r
72             if (!res) {\r
73                 stream->status |= _PDCLIB_ERRORFLAG;\r
74                 return EOF;\r
75             }\r
76 \r
77         }\r
78 \r
79         for ( ; stream->bufnlexp < stream->bufidx; stream->bufnlexp++ )\r
80         {\r
81             if (stream->buffer[stream->bufnlexp] == '\n' ) {\r
82                 if ( stream->bufidx == stream->bufend ) {\r
83                     // buffer is full. Need to print out everything up till now\r
84                     if( flushsubbuffer( stream, stream->bufnlexp - 1 ) )\r
85                     {\r
86                         return EOF;\r
87                     }\r
88                 }\r
89 \r
90                 // we have spare space in buffer. Shift everything 1char and\r
91                 // insert \r\r
92                 memmove( &stream->buffer[stream->bufnlexp + 1],\r
93                          &stream->buffer[stream->bufnlexp],\r
94                          stream->bufidx - stream->bufnlexp );\r
95                 stream->buffer[stream->bufnlexp] = '\r';\r
96 \r
97                 stream->bufnlexp++;\r
98                 stream->bufidx++;\r
99             }\r
100         }\r
101     }\r
102 #endif\r
103     return flushsubbuffer( stream, stream->bufidx );\r
104 }\r
105 \r
106 #endif\r
107 \r
108 \r
109 #ifdef TEST\r
110 #include <_PDCLIB_test.h>\r
111 \r
112 int main( void )\r
113 {\r
114     /* Testing covered by ftell.c */\r
115     return TEST_RESULTS;\r
116 }\r
117 \r
118 #endif\r
119 \r