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