1
0
mirror of https://github.com/adtools/clib2.git synced 2025-12-08 14:59:05 +00:00

Improvements for better read performance.

gets() now tries to copy as much data from the read buffer as possible, and will fall back onto using the __getc() macro only if necessary. This should improve performance on long lines, or crash faster if the read buffer happens to be too short. This is probably wasted on gets(), but you never know...
This commit is contained in:
obarthel
2019-08-24 13:55:31 +02:00
parent ae13cd77fc
commit 089ae11181

View File

@ -1,10 +1,8 @@
/*
* $Id: stdio_gets.c,v 1.6 2006-01-08 12:04:24 obarthel Exp $
*
* :ts=4
*
* Portable ISO 'C' (1994) runtime library for the Amiga computer
* Copyright (c) 2002-2015 by Olaf Barthel <obarthel (at) gmx.net>
* Copyright (c) 2002-2019 by Olaf Barthel <obarthel (at) gmx.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -46,6 +44,8 @@
char *
gets(char *s)
{
FILE * stream = stdin;
struct iob * file = (struct iob *)stream;
char * result = s;
int c;
@ -53,16 +53,16 @@ gets(char *s)
SHOWPOINTER(s);
assert( s != NULL && stdin != NULL );
assert( s != NULL );
if(__check_abort_enabled)
__check_abort();
flockfile(stdin);
flockfile(stream);
#if defined(CHECK_FOR_NULL_POINTERS)
{
if(s == NULL || stdin == NULL)
if(s == NULL)
{
SHOWMSG("invalid parameters");
@ -77,21 +77,55 @@ gets(char *s)
/* Take care of the checks and data structure changes that
* need to be handled only once for this stream.
*/
if(__fgetc_check(stdin) < 0)
if(__fgetc_check(stream) < 0)
{
result = NULL;
goto out;
}
/* So that we can tell error and 'end of file' conditions apart. */
clearerr(stdin);
clearerr(stream);
while(TRUE)
{
c = __getc(stdin);
/* If there is data in the buffer, try to copy it directly
into the string buffer. If there is a line feed in the
buffer, too, try to conclude the read operation. */
if(file->iob_BufferPosition < file->iob_BufferReadBytes)
{
size_t num_bytes_in_buffer = file->iob_BufferReadBytes - file->iob_BufferPosition;
const unsigned char * buffer = &file->iob_Buffer[file->iob_BufferPosition];
const unsigned char * lf;
/* Try to find a line feed character which could conclude
the read operation if the remaining buffer data, including
the line feed character, fit into the string buffer. */
lf = (unsigned char *)memchr(buffer, '\n', num_bytes_in_buffer);
if(lf != NULL)
{
size_t num_characters_in_line = lf + 1 - buffer;
/* Copy the remainder of the read buffer into the
string buffer, including the terminating line
feed character. */
memmove(s, buffer, num_characters_in_line);
file->iob_BufferPosition += num_characters_in_line;
/* And that concludes the line read operation. */
break;
}
memmove(s, buffer, num_bytes_in_buffer);
s += num_bytes_in_buffer;
file->iob_BufferPosition += num_bytes_in_buffer;
}
c = __getc(stream);
if(c == EOF)
{
if(ferror(stdin))
if(ferror(stream))
{
/* Just to be on the safe side. */
(*s) = '\0';
@ -120,7 +154,7 @@ gets(char *s)
out:
funlockfile(stdin);
funlockfile(stream);
RETURN(result);
return(result);