]> pd.if.org Git - pdclib.old/blob - functions/stdio/ftell.c
74bb902407a4672dfcb3c4beacc8519b16ab11ab
[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( struct _PDCLIB_file_t * 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( struct _PDCLIB_file_t * 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
42 #include <stdlib.h>
43
44 int main( void )
45 {
46     /* Testing all the basic I/O functions individually would result in lots
47        of duplicated code, so I took the liberty of lumping it all together
48        here.
49     */
50     /* The following functions delegate their tests to here:
51        fgetc fflush rewind fputc ungetc fseek
52        flushbuffer seek fillbuffer prepread prepwrite
53     */
54     char * buffer = (char*)malloc( 4 );
55     FILE * fh;
56     TESTCASE( ( fh = tmpfile() ) != NULL );
57     TESTCASE( setvbuf( fh, buffer, _IOLBF, 4 ) == 0 );
58     /* Testing ungetc() at offset 0 */
59     rewind( fh );
60     TESTCASE( ungetc( 'x', fh ) == 'x' );
61     TESTCASE( ftell( fh ) == -1l );
62     rewind( fh );
63     TESTCASE( ftell( fh ) == 0l );
64     /* Commence "normal" tests */
65     TESTCASE( fputc( '1', fh ) == '1' );
66     TESTCASE( fputc( '2', fh ) == '2' );
67     TESTCASE( fputc( '3', fh ) == '3' );
68     /* Positions incrementing as expected? */
69     TESTCASE( ftell( fh ) == 3l );
70     TESTCASE_NOREG( fh->pos.offset == 0l );
71     TESTCASE_NOREG( fh->bufidx == 3l );
72     /* Buffer properly flushed when full? */
73     TESTCASE( fputc( '4', fh ) == '4' );
74     TESTCASE_NOREG( fh->pos.offset == 4l );
75     TESTCASE_NOREG( fh->bufidx == 0 );
76     /* fflush() resetting positions as expected? */
77     TESTCASE( fputc( '5', fh ) == '5' );
78     TESTCASE( fflush( fh ) == 0 );
79     TESTCASE( ftell( fh ) == 5l );
80     TESTCASE_NOREG( fh->pos.offset == 5l );
81     TESTCASE_NOREG( fh->bufidx == 0l );
82     /* rewind() resetting positions as expected? */
83     rewind( fh );
84     TESTCASE( ftell( fh ) == 0l );
85     TESTCASE_NOREG( fh->pos.offset == 0 );
86     TESTCASE_NOREG( fh->bufidx == 0 );
87     /* Reading back first character after rewind for basic read check */
88     TESTCASE( fgetc( fh ) == '1' );
89     /* TODO: t.b.c. */
90     TESTCASE( fclose( fh ) == 0 );
91     return TEST_RESULTS;
92 }
93
94 #endif
95