projects
/
gnulib.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
autoupdate
[gnulib.git]
/
lib
/
getndelim2.c
diff --git
a/lib/getndelim2.c
b/lib/getndelim2.c
index
1a0ec11
..
9dcb9fe
100644
(file)
--- a/
lib/getndelim2.c
+++ b/
lib/getndelim2.c
@@
-76,7
+76,7
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
ssize_t bytes_stored = -1;
char *ptr = *lineptr;
size_t size = *linesize;
ssize_t bytes_stored = -1;
char *ptr = *lineptr;
size_t size = *linesize;
- bool
done = false
;
+ bool
found_delimiter
;
if (!ptr)
{
if (!ptr)
{
@@
-103,9
+103,11
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
flockfile (stream);
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;
int c IF_LINT (= 0);
const char *buffer;
@@
-120,7
+122,7
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
if (end)
{
buffer_len = end - buffer + 1;
if (end)
{
buffer_len = end - buffer + 1;
-
done
= true;
+
found_delimiter
= true;
}
}
}
}
}
}
@@
-136,7
+138,7
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
break;
}
if (c == delim1 || c == delim2)
break;
}
if (c == delim1 || c == delim2)
-
done
= true;
+
found_delimiter
= true;
buffer_len = 1;
}
buffer_len = 1;
}
@@
-144,13
+146,18
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
always (unless we get an error while reading the first byte)
NUL-terminate the line buffer. */
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;
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;
if (! (size < newsize && newsize <= nmax))
newsize = nmax;
@@
-171,6
+178,9
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
read_pos = size - nbytes_avail + ptr;
}
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;
if (1 < nbytes_avail)
{
size_t copy_len = nbytes_avail - 1;
@@
-183,9
+193,13
@@
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
read_pos += copy_len;
nbytes_avail -= copy_len;
}
read_pos += copy_len;
nbytes_avail -= copy_len;
}
+
+ /* Here still nbytes_avail > 0. */
+
if (buffer && freadseek (stream, buffer_len))
goto unlock_done;
}
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. */
/* Done - NUL terminate and return the number of bytes read.
At this point we know that nbytes_avail >= 1. */