]> pd.if.org Git - pdclib.old/blob - functions/stdio/ftell.c
Namespace cleanliness: Rename all ***_unlocked functions to _PDCLIB_***_unlocked.
[pdclib.old] / functions / stdio / ftell.c
1 /* $Id$ */
2
3 /* ftell( FILE * )
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 <stdint.h>
11 #include <limits.h>
12 #include <errno.h>
13
14 #ifndef REGTEST
15 #include <_PDCLIB_io.h>
16
17 long int _PDCLIB_ftell_unlocked( FILE * stream )
18 {
19     uint_fast64_t off64 = _PDCLIB_ftell64_unlocked( stream );
20
21     if ( off64 > LONG_MAX )
22     {
23         /* integer overflow */
24         errno = ERANGE;
25         return -1;
26     }
27     return off64;
28 }
29
30 long int ftell( FILE * stream )
31 {
32     _PDCLIB_flockfile( stream );
33     long int off = _PDCLIB_ftell_unlocked( stream );
34     _PDCLIB_funlockfile( stream );
35     return off;
36 }
37
38 #endif
39
40 #ifdef TEST
41 #include <_PDCLIB_test.h>
42 #include <stdlib.h>
43 #ifndef REGTEST
44 #include <_PDCLIB_io.h>
45 #endif
46
47 int main( void )
48 {
49     /* Testing all the basic I/O functions individually would result in lots
50        of duplicated code, so I took the liberty of lumping it all together
51        here.
52     */
53     /* The following functions delegate their tests to here:
54        fgetc fflush rewind fputc ungetc fseek
55        flushbuffer seek fillbuffer prepread prepwrite
56     */
57     char * buffer = (char*)malloc( 4 );
58     FILE * fh;
59     TESTCASE( ( fh = tmpfile() ) != NULL );
60     TESTCASE( setvbuf( fh, buffer, _IOLBF, 4 ) == 0 );
61     /* Testing ungetc() at offset 0 */
62     rewind( fh );
63     TESTCASE( ungetc( 'x', fh ) == 'x' );
64     TESTCASE( ftell( fh ) == -1l );
65     rewind( fh );
66     TESTCASE( ftell( fh ) == 0l );
67     /* Commence "normal" tests */
68     TESTCASE( fputc( '1', fh ) == '1' );
69     TESTCASE( fputc( '2', fh ) == '2' );
70     TESTCASE( fputc( '3', fh ) == '3' );
71     /* Positions incrementing as expected? */
72     TESTCASE( ftell( fh ) == 3l );
73     TESTCASE_NOREG( fh->pos.offset == 0l );
74     TESTCASE_NOREG( fh->bufidx == 3l );
75     /* Buffer properly flushed when full? */
76     TESTCASE( fputc( '4', fh ) == '4' );
77     TESTCASE_NOREG( fh->pos.offset == 4l );
78     TESTCASE_NOREG( fh->bufidx == 0 );
79     /* fflush() resetting positions as expected? */
80     TESTCASE( fputc( '5', fh ) == '5' );
81     TESTCASE( fflush( fh ) == 0 );
82     TESTCASE( ftell( fh ) == 5l );
83     TESTCASE_NOREG( fh->pos.offset == 5l );
84     TESTCASE_NOREG( fh->bufidx == 0l );
85     /* rewind() resetting positions as expected? */
86     rewind( fh );
87     TESTCASE( ftell( fh ) == 0l );
88     TESTCASE_NOREG( fh->pos.offset == 0 );
89     TESTCASE_NOREG( fh->bufidx == 0 );
90     /* Reading back first character after rewind for basic read check */
91     TESTCASE( fgetc( fh ) == '1' );
92     /* TODO: t.b.c. */
93     TESTCASE( fclose( fh ) == 0 );
94     return TEST_RESULTS;
95 }
96
97 #endif
98