1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-09-01 02:34:55 +00:00

Extend freadptr to return also the buffer size.

This commit is contained in:
Bruno Haible
2008-03-10 00:23:20 +01:00
parent f47f70aaf3
commit 03400ebfaa
7 changed files with 176 additions and 67 deletions
+17
View File
@@ -1,3 +1,20 @@
2008-03-09 Bruno Haible <bruno@clisp.org>
Extend freadptr to return also the buffer size.
* lib/freadptr.h (freadptr): Add sizep argument.
* lib/freadptr.c: Include freadptr.h, not freadahead.h.
(freadptr): Add sizep argument. Determine buffer size like freadahead
does.
* tests/test-freadptr.c: Don't include freadahead.h.
(main): Adapt for new calling convention of freadptr.
* tests/test-freadptr2.c: New file, based on tests/test-freadahead.c.
* tests/test-freadptr2.sh: New file, based on tests/test-freadahead.sh.
* modules/freadptr-tests (Files): Add tests/test-freadptr2.c,
tests/test-freadptr2.sh.
(Depends): Remove freadahead.
(TESTS): Add test-freadptr2.sh.
(check_PROGRAMS): Add test-freadptr2.
2008-03-09 Bruno Haible <bruno@clisp.org>
* doc/Makefile (%.pdf): Explain how to remedy the save_size error.
+42 -3
View File
@@ -17,15 +17,29 @@
#include <config.h>
/* Specification. */
#include "freadahead.h"
#include "freadptr.h"
const char *
freadptr (FILE *fp)
freadptr (FILE *fp, size_t *sizep)
{
size_t size;
/* Keep this code in sync with freadahead! */
#if defined _IO_ferror_unlocked /* GNU libc, BeOS */
if (fp->_IO_write_ptr > fp->_IO_write_base)
return NULL;
size = fp->_IO_read_end - fp->_IO_read_ptr;
if (size == 0)
return NULL;
*sizep = size;
return (const char *) fp->_IO_read_ptr;
#elif defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
if ((fp->_flags & __SWR) != 0 || fp->_r < 0)
return NULL;
size = fp->_r;
if (size == 0)
return NULL;
*sizep = size;
return (const char *) fp->_p;
#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
@@ -36,19 +50,44 @@ freadptr (FILE *fp)
int _file; \
unsigned int _flag; \
} *) fp)
if ((fp_->_flag & _IOWRT) != 0)
return NULL;
size = fp_->_cnt;
if (size == 0)
return NULL;
*sizep = size;
return (const char *) fp_->_ptr;
# else
if ((fp->_flag & _IOWRT) != 0)
return NULL;
size = fp->_cnt;
if (size == 0)
return NULL;
*sizep = size;
return (const char *) fp->_ptr;
# endif
#elif defined __UCLIBC__ /* uClibc */
# ifdef __STDIO_BUFFERS
if (fp->__modeflags & __FLAG_WRITING)
return NULL;
size = fp->__bufread - fp->__bufpos;
if (size == 0)
return NULL;
*sizep = size;
return (const char *) fp->__bufpos;
# else
return NULL;
# endif
#elif defined __QNX__ /* QNX */
if ((fp->_Mode & 0x2000 /* _MWRITE */) != 0)
return NULL;
/* fp->_Buf <= fp->_Next <= fp->_Rend */
size = fp->_Rend - fp->_Next;
if (size == 0)
return NULL;
*sizep = size;
return (const char *) fp->_Next;
#else
#error "Please port gnulib freadptr.c to your platform! Look at the definition of getc, getc_unlocked on your system, then report this to bug-gnulib."
#error "Please port gnulib freadptr.c to your platform! Look at the definition of fflush, fread, getc, getc_unlocked on your system, then report this to bug-gnulib."
#endif
}
+6 -8
View File
@@ -22,19 +22,17 @@ extern "C" {
#endif
/* Assuming the stream STREAM is open for reading:
Return a pointer to the input buffer of STREAM.
If freadahead (STREAM) > 0, the result is either a pointer to
freadahead (STREAM) bytes, or NULL. The latter case can happen after
use of 'ungetc (..., STREAM)'.
If freadahead (STREAM) == 0, the result is not usable; it may be NULL.
In this case, you should use getc (STREAM), fgetc (STREAM), or
fread (..., STREAM) to access the input from STREAM.
Return a pointer to the input buffer of STREAM, or NULL.
If the returned pointer is non-NULL, *SIZEP is set to the (positive) size
of the input buffer.
If the returned pointer is NULL, you should use getc (STREAM),
fgetc (STREAM), or fread (..., STREAM) to access the input from STREAM.
The resulting pointer becomes invalid upon any operation on STREAM.
STREAM must not be wide-character oriented. */
extern const char * freadptr (FILE *stream);
extern const char * freadptr (FILE *stream, size_t *sizep);
#ifdef __cplusplus
}
+4 -3
View File
@@ -1,15 +1,16 @@
Files:
tests/test-freadptr.c
tests/test-freadptr.sh
tests/test-freadptr2.c
tests/test-freadptr2.sh
Depends-on:
lseek
freadahead
unistd
configure.ac:
Makefile.am:
TESTS += test-freadptr.sh
TESTS += test-freadptr.sh test-freadptr2.sh
TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'
check_PROGRAMS += test-freadptr
check_PROGRAMS += test-freadptr test-freadptr2
+31 -53
View File
@@ -25,8 +25,6 @@
#include <string.h>
#include <unistd.h>
#include "freadahead.h"
#define ASSERT(expr) \
do \
{ \
@@ -46,80 +44,60 @@ main (int argc, char **argv)
ASSERT (fread (buf, 1, nbytes, stdin) == nbytes);
if (lseek (0, 0, SEEK_CUR) == nbytes)
/* An unbuffered stdio, such as BeOS or on uClibc compiled without
__STDIO_BUFFERS. Or stdin is a pipe. */
ASSERT (freadahead (stdin) == 0);
{
/* An unbuffered stdio, such as BeOS or on uClibc compiled without
__STDIO_BUFFERS. Or stdin is a pipe. */
size_t size;
ASSERT (freadptr (stdin, &size) == NULL);
}
else
{
/* Normal buffered stdio. */
const char stdin_contents[] =
"#!/bin/sh\n\n./test-freadptr${EXEEXT} 5 < \"$srcdir/test-freadptr.sh\" || exit 1\ncat \"$srcdir/test-freadptr.sh\" | ./test-freadptr${EXEEXT} 5 || exit 1\nexit 0\n";
const char *expected = stdin_contents + nbytes;
size_t available;
size_t available1;
size_t available2;
size_t available3;
/* Test normal behaviour. */
available = freadahead (stdin);
ASSERT (available != 0);
ASSERT (available <= strlen (expected));
{
const char *ptr = freadptr (stdin);
const char *ptr = freadptr (stdin, &available1);
ASSERT (ptr != NULL);
ASSERT (memcmp (ptr, expected, available) == 0);
ASSERT (available1 != 0);
ASSERT (available1 <= strlen (expected));
ASSERT (memcmp (ptr, expected, available1) == 0);
}
/* Test behaviour after normal ungetc. */
ungetc (fgetc (stdin), stdin);
available2 = freadahead (stdin);
ASSERT (/* available2 == available - 1 || */ available2 == available);
#if 0
if (available2 == available - 1)
{
ASSERT (freadptr (stdin) == NULL);
}
else
#endif
{
const char *ptr = freadptr (stdin);
{
const char *ptr = freadptr (stdin, &available2);
ASSERT (ptr != NULL);
ASSERT (memcmp (ptr, expected, available) == 0);
}
if (ptr != NULL)
{
ASSERT (available2 == available1);
ASSERT (memcmp (ptr, expected, available2) == 0);
}
}
/* Test behaviour after arbitrary ungetc. */
fgetc (stdin);
ungetc ('@', stdin);
available3 = freadahead (stdin);
ASSERT (available3 == 0 || available3 == 1 || /* available3 == available - 1 || */ available3 == available);
if (available3 == 0)
;
else if (available3 == 1)
{
const char *ptr = freadptr (stdin);
{
const char *ptr = freadptr (stdin, &available3);
if (ptr != NULL)
{
ASSERT (ptr[0] == '@');
}
}
#if 0
else if (available3 == available - 1)
{
ASSERT (freadptr (stdin) == NULL);
}
#endif
else
{
const char *ptr = freadptr (stdin);
if (ptr != NULL)
{
ASSERT (ptr[0] == '@');
ASSERT (memcmp (ptr + 1, expected + 1, available - 1) == 0);
}
}
if (ptr != NULL)
{
ASSERT (available3 == 1 || available3 == available1);
ASSERT (ptr[0] == '@');
if (available3 > 1)
{
ASSERT (memcmp (ptr + 1, expected + 1, available3 - 1) == 0);
}
}
}
}
return 0;
+71
View File
@@ -0,0 +1,71 @@
/* Test of freadptr() function.
Copyright (C) 2007-2008 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
#include <config.h>
#include "freadptr.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ASSERT(expr) \
do \
{ \
if (!(expr)) \
{ \
fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
abort (); \
} \
} \
while (0)
static int
freadptrbufsize (FILE *fp)
{
size_t size = 0;
freadptr (fp, &size);
return size;
}
int
main (int argc, char **argv)
{
int nbytes = atoi (argv[1]);
if (nbytes > 0)
{
void *buf = malloc (nbytes);
ASSERT (fread (buf, 1, nbytes, stdin) == nbytes);
}
if (nbytes == 0)
ASSERT (freadptrbufsize (stdin) == 0);
else
{
if (lseek (0, 0, SEEK_CUR) == nbytes)
/* An unbuffered stdio, such as BeOS or on uClibc compiled without
__STDIO_BUFFERS. */
ASSERT (freadptrbufsize (stdin) == 0);
else
/* Normal buffered stdio. */
ASSERT (freadptrbufsize (stdin) != 0);
}
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
./test-freadptr2${EXEEXT} 0 < "$srcdir/test-freadptr2.sh" || exit 1
./test-freadptr2${EXEEXT} 5 < "$srcdir/test-freadptr2.sh" || exit 1
exit 0