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:
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user