]> pd.if.org Git - pdclib/blob - functions/stdio/setvbuf.c
Merged branch stdio_rewrite back into trunk.
[pdclib] / functions / stdio / setvbuf.c
1 /* $Id$ */
2
3 /* setvbuf( FILE *, char *, int, size_t )
4
5    This file is part of the Public Domain C Library (PDCLib).
6    Permission is granted to use, modify, and / or redistribute at will.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <limits.h>
12
13 #ifndef REGTEST
14
15 int setvbuf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mode, size_t size )
16 {
17     switch ( mode )
18     {
19         case _IONBF:
20             /* When unbuffered I/O is requested, we keep the buffer anyway, as
21                we don't want to e.g. flush the stream for every character of a
22                stream being printed.
23             */
24             break;
25         case _IOFBF:
26         case _IOLBF:
27             if ( size > INT_MAX || size == NULL )
28             {
29                 /* PDCLib only supports buffers up to INT_MAX in size. A size
30                    of zero doesn't make sense.
31                 */
32                 return -1;
33             }
34             if ( buf == NULL )
35             {
36                 /* User requested buffer size, but leaves it to library to
37                    allocate the buffer.
38                 */
39                 if ( ( stream->bufsize < size ) || ( stream->bufsize > ( size << 1 ) ) )
40                 {
41                     /* If current buffer is big enough for requested size, but
42                        not over twice as big (and wasting memory space), we use
43                        the current buffer (i.e., do nothing), to save the
44                        malloc() / free() overhead.
45                     */
46                     /* Free the buffer allocated by fopen(), and allocate a new
47                        one.
48                     */
49                     if ( ( buf = (char *) malloc( size ) ) == NULL )
50                     {
51                         /* Out of memory error. */
52                         return -1;
53                     }
54                 }
55             }
56             else
57             {
58                 /* User provided buffer -> set flag to not free() the buffer
59                    on fclose().
60                 */
61                 stream->status &= ~ _PDCLIB_LIBBUFFER;
62             }
63             free( stream->buffer );
64             stream->buffer = buf;
65             stream->bufsize = size;
66             break;
67         default:
68             /* If mode is something else than _IOFBF, _IOLBF or _IONBF -> exit */
69             return -1;
70     }
71     /* Deleting current buffer mode */
72     stream->status &= ~( _IOFBF | _IOLBF | _IONBF );
73     /* Set user-defined mode */
74     stream->status |= mode;
75     return 0;
76 }
77
78 #endif
79
80 #ifdef TEST
81 #include <_PDCLIB_test.h>
82
83 #include <errno.h>
84
85 #define BUFFERSIZE 500
86
87 int main( void )
88 {
89 #ifndef REGTEST
90     char const * const filename = "testfile";
91     char buffer[ BUFFERSIZE ];
92     FILE * fh;
93     remove( filename );
94     /* full buffered, user-supplied buffer */
95     TESTCASE( ( fh = fopen( filename, "w" ) ) != NULL );
96     TESTCASE( setvbuf( fh, buffer, _IOFBF, BUFFERSIZE ) == 0 );
97     TESTCASE( fh->buffer == buffer );
98     TESTCASE( fh->bufsize == BUFFERSIZE );
99     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOFBF );
100     TESTCASE( fclose( fh ) == 0 );
101     TESTCASE( remove( filename ) == 0 );
102     /* line buffered, lib-supplied buffer */
103     TESTCASE( ( fh = fopen( filename, "w" ) ) != NULL );
104     TESTCASE( setvbuf( fh, NULL, _IOLBF, BUFFERSIZE ) == 0 );
105     TESTCASE( fh->buffer != NULL );
106     TESTCASE( fh->bufsize == BUFFERSIZE );
107     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOLBF );
108     TESTCASE( fclose( fh ) == 0 );
109     TESTCASE( remove( filename ) == 0 );
110     /* not buffered, user-supplied buffer */
111     TESTCASE( ( fh = fopen( filename, "w" ) ) != NULL );
112     TESTCASE( setvbuf( fh, buffer, _IONBF, BUFFERSIZE ) == 0 );
113     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IONBF );
114     TESTCASE( fclose( fh ) == 0 );
115     TESTCASE( remove( filename ) == 0 );
116 #else
117     puts( " NOTEST setvbuf() test driver is PDCLib-specific." );
118 #endif
119     return TEST_RESULTS;
120 }
121
122 #endif
123