ssize_t bytes_stored = -1;
char *ptr = *lineptr;
size_t size = *linesize;
- bool done = false;
+ bool found_delimiter;
if (!ptr)
{
flockfile (stream);
- while (!done)
+ found_delimiter = false;
+ do
{
- /* Here always ptr + size == read_pos + nbytes_avail. */
+ /* Here always ptr + size == read_pos + nbytes_avail.
+ Also nbytes_avail > 0 || size < nmax. */
int c IF_LINT (= 0);
const char *buffer;
if (end)
{
buffer_len = end - buffer + 1;
- done = true;
+ found_delimiter = true;
}
}
}
break;
}
if (c == delim1 || c == delim2)
- done = true;
+ found_delimiter = true;
buffer_len = 1;
}
always (unless we get an error while reading the first byte)
NUL-terminate the line buffer. */
- if (nbytes_avail < 1 + buffer_len && size < nmax)
+ if (nbytes_avail < buffer_len + 1 && size < nmax)
{
+ /* Grow size proportionally, not linearly, to avoid O(n^2)
+ running time. */
size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size;
char *newptr;
- if (newsize < buffer_len)
- newsize = buffer_len + size;
+ /* Increase newsize so that it becomes
+ >= (read_pos - ptr) + buffer_len. */
+ if (newsize - (read_pos - ptr) < buffer_len + 1)
+ newsize = (read_pos - ptr) + buffer_len + 1;
+ /* Respect nmax. This handles possible integer overflow. */
if (! (size < newsize && newsize <= nmax))
newsize = nmax;
read_pos = size - nbytes_avail + ptr;
}
+ /* Here, if size < nmax, nbytes_avail >= buffer_len + 1.
+ If size == nmax, nbytes_avail > 0. */
+
if (1 < nbytes_avail)
{
size_t copy_len = nbytes_avail - 1;
read_pos += copy_len;
nbytes_avail -= copy_len;
}
+
+ /* Here still nbytes_avail > 0. */
+
if (buffer && freadseek (stream, buffer_len))
goto unlock_done;
}
+ while (!found_delimiter);
/* Done - NUL terminate and return the number of bytes read.
At this point we know that nbytes_avail >= 1. */