]> pd.if.org Git - pdclib.old/blob - functions/stdio/setvbuf.c
PDCLIB-2 c32rtomb: likewise missing NULL destination check
[pdclib.old] / 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 #include <_PDCLIB_io.h>
15
16 int setvbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mode, size_t size )
17 {
18     _PDCLIB_flockfile( stream );
19     switch ( mode )
20     {
21         case _IONBF:
22             /* When unbuffered I/O is requested, we keep the buffer anyway, as
23                we don't want to e.g. flush the stream for every character of a
24                stream being printed.
25             */
26             break;
27         case _IOFBF:
28         case _IOLBF:
29             if ( size > INT_MAX || size == 0 )
30             {
31                 /* PDCLib only supports buffers up to INT_MAX in size. A size
32                    of zero doesn't make sense.
33                 */
34                 _PDCLIB_funlockfile( stream );
35                 return -1;
36             }
37             if ( buf == NULL )
38             {
39                 /* User requested buffer size, but leaves it to library to
40                    allocate the buffer.
41                 */
42                 /* If current buffer is big enough for requested size, but not
43                    over twice as big (and wasting memory space), we use the
44                    current buffer (i.e., do nothing), to save the malloc() / 
45                    free() overhead.
46                 */
47                 if ( ( stream->bufsize < size ) || ( stream->bufsize > ( size << 1 ) ) )
48                 {
49                     /* Buffer too small, or much too large - allocate. */
50                     if ( ( buf = (char *) malloc( size ) ) == NULL )
51                     {
52                         /* Out of memory error. */
53                         _PDCLIB_funlockfile( stream );
54                         return -1;
55                     }
56                     /* This buffer must be free()d on fclose() */
57                     stream->status |= _PDCLIB_FREEBUFFER;
58                 }
59             }
60             stream->buffer = buf;
61             stream->bufsize = size;
62             break;
63         default:
64             /* If mode is something else than _IOFBF, _IOLBF or _IONBF -> exit */
65             _PDCLIB_funlockfile( stream );
66             return -1;
67     }
68     /* Deleting current buffer mode */
69     stream->status &= ~( _IOFBF | _IOLBF | _IONBF );
70     /* Set user-defined mode */
71     stream->status |= mode;
72     _PDCLIB_funlockfile( stream );
73     return 0;
74 }
75
76 #endif
77
78 #ifdef TEST
79 #include <_PDCLIB_test.h>
80 #include <errno.h>
81 #ifndef REGTEST
82 #include <_PDCLIB_io.h>
83 #endif
84 #define BUFFERSIZE 500
85
86 int main( void )
87 {
88 #ifndef REGTEST
89     char buffer[ BUFFERSIZE ];
90     FILE * fh;
91     /* full buffered, user-supplied buffer */
92     TESTCASE( ( fh = tmpfile() ) != NULL );
93     TESTCASE( setvbuf( fh, buffer, _IOFBF, BUFFERSIZE ) == 0 );
94     TESTCASE( fh->buffer == buffer );
95     TESTCASE( fh->bufsize == BUFFERSIZE );
96     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOFBF );
97     TESTCASE( fclose( fh ) == 0 );
98     /* line buffered, lib-supplied buffer */
99     TESTCASE( ( fh = tmpfile() ) != NULL );
100     TESTCASE( setvbuf( fh, NULL, _IOLBF, BUFFERSIZE ) == 0 );
101     TESTCASE( fh->buffer != NULL );
102     TESTCASE( fh->bufsize == BUFFERSIZE );
103     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOLBF );
104     TESTCASE( fclose( fh ) == 0 );
105     /* not buffered, user-supplied buffer */
106     TESTCASE( ( fh = tmpfile() ) != NULL );
107     TESTCASE( setvbuf( fh, buffer, _IONBF, BUFFERSIZE ) == 0 );
108     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IONBF );
109     TESTCASE( fclose( fh ) == 0 );
110 #else
111     puts( " NOTEST setvbuf() test driver is PDCLib-specific." );
112 #endif
113     return TEST_RESULTS;
114 }
115
116 #endif
117