]> pd.if.org Git - pdclib/blob - functions/stdio/fwrite.c
Whitespace cleanups.
[pdclib] / functions / stdio / fwrite.c
1 /* fwrite( const void *, size_t, size_t, FILE * )
2
3    This file is part of the Public Domain C Library (PDCLib).
4    Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #include <stdio.h>
8 #include <stdbool.h>
9 #include <string.h>
10
11 #ifndef REGTEST
12
13 #include "_PDCLIB_glue.h"
14
15 size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, struct _PDCLIB_file_t * _PDCLIB_restrict stream )
16 {
17     if ( _PDCLIB_prepwrite( stream ) == EOF )
18     {
19         return 0;
20     }
21     _PDCLIB_size_t offset = 0;
22     /* TODO: lineend */
23     /* bool lineend = false; */
24     size_t nmemb_i;
25     for ( nmemb_i = 0; nmemb_i < nmemb; ++nmemb_i )
26     {
27         for ( size_t size_i = 0; size_i < size; ++size_i )
28         {
29             if ( ( stream->buffer[ stream->bufidx++ ] = ((char*)ptr)[ nmemb_i * size + size_i ] ) == '\n' )
30             {
31                 /* Remember last newline, in case we have to do a partial line-buffered flush */
32                 offset = stream->bufidx;
33                 /* lineend = true; */
34             }
35             if ( stream->bufidx == stream->bufsize )
36             {
37                 if ( _PDCLIB_flushbuffer( stream ) == EOF )
38                 {
39                     /* Returning number of objects completely buffered */
40                     return nmemb_i;
41                 }
42                 /* lineend = false; */
43             }
44         }
45     }
46     /* Fully-buffered streams are OK. Non-buffered streams must be flushed,
47        line-buffered streams only if there's a newline in the buffer.
48     */
49     switch ( stream->status & ( _IONBF | _IOLBF ) )
50     {
51         case _IONBF:
52             if ( _PDCLIB_flushbuffer( stream ) == EOF )
53             {
54                 /* We are in a pinch here. We have an error, which requires a
55                    return value < nmemb. On the other hand, all objects have
56                    been written to buffer, which means all the caller had to
57                    do was removing the error cause, and re-flush the stream...
58                    Catch 22. We'll return a value one short, to indicate the
59                    error, and can't really do anything about the inconsistency.
60                 */
61                 return nmemb_i - 1;
62             }
63             break;
64         case _IOLBF:
65             {
66             size_t bufidx = stream->bufidx;
67             stream->bufidx = offset;
68             if ( _PDCLIB_flushbuffer( stream ) == EOF )
69             {
70                 /* See comment above. */
71                 stream->bufidx = bufidx;
72                 return nmemb_i - 1;
73             }
74             stream->bufidx = bufidx - offset;
75             memmove( stream->buffer, stream->buffer + offset, stream->bufidx );
76             }
77     }
78     return nmemb_i;
79 }
80
81 #endif
82
83 #ifdef TEST
84
85 #include "_PDCLIB_test.h"
86
87 int main( void )
88 {
89     /* Testing covered by fread(). */
90     return TEST_RESULTS;
91 }
92
93 #endif