#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "getndelim2.h"
#include <stdlib.h>
#include <stddef.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#include <limits.h>
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#ifndef PTRDIFF_MAX
# define PTRDIFF_MAX ((ptrdiff_t) (SIZE_MAX / 2))
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#ifndef SSIZE_MAX
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
#endif
#define GETNDELIM2_MAXIMUM (PTRDIFF_MAX < SSIZE_MAX ? PTRDIFF_MAX : SSIZE_MAX)
#define MIN_CHUNK 64
ssize_t
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
int delim1, int delim2, FILE *stream)
{
size_t nbytes_avail;
char *read_pos;
ssize_t bytes_stored = -1;
char *ptr = *lineptr;
size_t size = *linesize;
if (!ptr)
{
size = nmax < MIN_CHUNK ? nmax : MIN_CHUNK;
ptr = malloc (size);
if (!ptr)
return -1;
}
if (size < offset)
goto done;
nbytes_avail = size - offset;
read_pos = ptr + offset;
if (nbytes_avail == 0 && nmax <= size)
goto done;
for (;;)
{
int c;
if (nbytes_avail < 2 && size < nmax)
{
size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size;
char *newptr;
if (! (size < newsize && newsize <= nmax))
newsize = nmax;
if (GETNDELIM2_MAXIMUM < newsize - offset)
{
size_t newsizemax = offset + GETNDELIM2_MAXIMUM + 1;
if (size == newsizemax)
goto done;
newsize = newsizemax;
}
nbytes_avail = newsize - (read_pos - ptr);
newptr = realloc (ptr, newsize);
if (!newptr)
goto done;
ptr = newptr;
size = newsize;
read_pos = size - nbytes_avail + ptr;
}
c = getc (stream);
if (c == EOF)
{
if (read_pos == ptr)
goto done;
else
break;
}
if (nbytes_avail >= 2)
{
*read_pos++ = c;
nbytes_avail--;
}
if (c == delim1 || c == delim2)
break;
}
*read_pos = '\0';
bytes_stored = read_pos - (ptr + offset);
done:
*lineptr = ptr;
*linesize = size;
return bytes_stored;
}