--- linebuffer_2.0.17.c Tue Nov 6 12:20:28 2001 +++ linebuffer.c Fri Nov 23 19:34:20 2001 @@ -29,6 +29,8 @@ char *xmalloc (); char *xrealloc (); void free (); +char *memchr (); +char *memrchr (); /* Initialize linebuffer LINEBUFFER for use. */ @@ -42,12 +44,14 @@ /* Read an arbitrarily long line of text from STREAM into LINEBUFFER. Keep the newline; append a newline if it's the last line of a file - that ends in a non-newline character. Do not null terminate. - Return LINEBUFFER, except at end of file return 0. */ - + that ends in a non-newline character. Do not null terminate. + Therefore the stream can contain NULLs and the length (including + the newline) is returned in linebuffer->size. + Return LINEBUFFER, except at end of file or error return NULL.*/ struct linebuffer * readline (struct linebuffer *linebuffer, FILE *stream) { +#if HAVE_GETC_UNLOCKED int c; char *buffer = linebuffer->buffer; char *p = linebuffer->buffer; @@ -80,6 +84,57 @@ while (c != '\n'); linebuffer->length = p - buffer; +#else + size_t fgetSize; + char* fgetPos; + char* newline; + char* fgetsRet; + char* buf; + + fgetPos = buf = linebuffer->buffer; + fgetSize = linebuffer->size; + + if (feof (stream) || ferror (stream)) + return NULL; + + while(1) + { + memset (fgetPos, '\1', fgetSize); /* Can be anything except 0 */ + if ((fgetsRet=fgets (fgetPos, (int) fgetSize, stream))) + { + newline=memchr (fgetPos, '\n', fgetSize); + if (!newline) /* No \n => buffer possibly full */ + { + if (buf[linebuffer->size-1] == '\0') /*buffer full*/ + { + if (!feof (stream)) + { + fgetSize = linebuffer->size + 1; + linebuffer->size *= 2; + buf = (char *) xrealloc (buf, linebuffer->size); + linebuffer->buffer = buf; + fgetPos = buf + fgetSize -2; + continue; + } + else /* small chance incomplete line fit buffer exactly */ + { + newline = &buf[linebuffer->size-1]; + *newline = '\n'; + } + } + else /* incomplete line received */ + { + newline=memrchr (fgetPos, '\0', fgetSize); + *newline = '\n'; + } + } + } + else + return NULL; + break; + } + linebuffer->length = newline - buf + 1; +#endif return linebuffer; }