1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* Copyright 2002, Red Hat Inc. - all rights reserved */
/*
FUNCTION
<<getdelim>>---read a line up to a specified line delimiter
INDEX
getdelim
SYNOPSIS
#include <stdio.h>
int getdelim(char **<[bufptr]>, size_t *<[n]>,
int <[delim]>, FILE *<[fp]>);
DESCRIPTION
<<getdelim>> reads a file <[fp]> up to and possibly including a specified
delimiter <[delim]>. The line is read into a buffer pointed to
by <[bufptr]> and designated with size *<[n]>. If the buffer is
not large enough, it will be dynamically grown by <<getdelim>>.
As the buffer is grown, the pointer to the size <[n]> will be
updated.
RETURNS
<<getdelim>> returns <<-1>> if no characters were successfully read;
otherwise, it returns the number of bytes successfully read.
At end of file, the result is nonzero.
PORTABILITY
<<getdelim>> is a glibc extension.
No supporting OS subroutines are directly required.
*/
#define _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#include <_ansi.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "local.h"
#define MIN_LINE_SIZE 4
#define DEFAULT_LINE_SIZE 128
ssize_t
__getdelim (char **bufptr,
size_t *n,
int delim,
FILE *fp)
{
char *buf;
char *ptr;
size_t newsize, numbytes;
int pos;
int ch;
int cont;
if (fp == NULL || bufptr == NULL || n == NULL)
{
errno = EINVAL;
return -1;
}
buf = *bufptr;
if (buf == NULL || *n < MIN_LINE_SIZE)
{
buf = (char *)realloc (*bufptr, DEFAULT_LINE_SIZE);
if (buf == NULL)
{
return -1;
}
*bufptr = buf;
*n = DEFAULT_LINE_SIZE;
}
CHECK_INIT (_REENT, fp);
_newlib_flockfile_start (fp);
numbytes = *n;
ptr = buf;
cont = 1;
while (cont)
{
/* fill buffer - leaving room for nul-terminator */
while (--numbytes > 0)
{
if ((ch = getc_unlocked (fp)) == EOF)
{
cont = 0;
break;
}
else
{
*ptr++ = ch;
if (ch == delim)
{
cont = 0;
break;
}
}
}
if (cont)
{
/* Buffer is too small so reallocate a larger buffer. */
pos = ptr - buf;
newsize = (*n << 1);
buf = realloc (buf, newsize);
if (buf == NULL)
{
cont = 0;
break;
}
/* After reallocating, continue in new buffer */
*bufptr = buf;
*n = newsize;
ptr = buf + pos;
numbytes = newsize - pos;
}
}
_newlib_flockfile_end (fp);
/* if no input data, return failure */
if (ptr == buf)
return -1;
/* otherwise, nul-terminate and return number of bytes read */
*ptr = '\0';
return (ssize_t)(ptr - buf);
}
|