1228060Sbapt/* getline.c -- Replacement for GNU C library function getline 2228060Sbapt 3228060SbaptCopyright (C) 1993, 1996, 2001-2002 Free Software Foundation, Inc. 4228060Sbapt 5228060SbaptThis program is free software; you can redistribute it and/or 6228060Sbaptmodify it under the terms of the GNU General Public License as 7228060Sbaptpublished by the Free Software Foundation; either version 2 of the 8228060SbaptLicense, or (at your option) any later version. 9228060Sbapt 10228060SbaptThis program is distributed in the hope that it will be useful, but 11228060SbaptWITHOUT ANY WARRANTY; without even the implied warranty of 12228060SbaptMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13228060SbaptGeneral Public License for more details. 14228060Sbapt 15228060SbaptYou should have received a copy of the GNU General Public License 16228060Sbaptalong with this program; if not, write to the Free Software 17228060SbaptFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 18228060SbaptUSA. */ 19228060Sbapt 20228060Sbapt/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ 21228060Sbapt 22228060Sbapt/* Specification. */ 23228060Sbapt#include "getline.h" 24228060Sbapt 25228060Sbapt#include <stddef.h> 26228060Sbapt#include <stdio.h> 27228060Sbapt#include <string.h> 28228060Sbapt#include <assert.h> 29228060Sbapt 30228060Sbapt/* Always add at least this many bytes when extending the buffer. */ 31228060Sbapt#define MIN_CHUNK 64 32228060Sbapt 33228060Sbapt/* Reads up to (and including) a TERMINATOR from STREAM into *LINEPTR + OFFSET 34228060Sbapt (and null-terminate it). *LINEPTR is a pointer returned from new [] (or 35228060Sbapt NULL), pointing to *N characters of space. It is realloc'd as 36228060Sbapt necessary. Returns the number of characters read (not including the 37228060Sbapt null terminator), or -1 on error or immediate EOF. 38228060Sbapt NOTE: There is another getstr() function declared in <curses.h>. */ 39228060Sbapt 40228060Sbaptstatic int 41228060Sbaptgetstr (char **lineptr, size_t *n, FILE *stream, char terminator, size_t offset) 42228060Sbapt{ 43228060Sbapt size_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */ 44228060Sbapt char *read_pos; /* Where we're reading into *LINEPTR. */ 45228060Sbapt 46228060Sbapt if (!lineptr || !n || !stream) 47228060Sbapt return -1; 48228060Sbapt 49228060Sbapt if (!*lineptr) 50228060Sbapt { 51228060Sbapt *n = MIN_CHUNK; 52228060Sbapt *lineptr = new char[*n]; 53228060Sbapt } 54228060Sbapt 55228060Sbapt nchars_avail = *n - offset; 56228060Sbapt read_pos = *lineptr + offset; 57228060Sbapt 58228060Sbapt for (;;) 59228060Sbapt { 60228060Sbapt register int c = getc (stream); 61228060Sbapt 62228060Sbapt /* We always want at least one char left in the buffer, since we 63228060Sbapt always (unless we get an error while reading the first char) 64228060Sbapt NUL-terminate the line buffer. */ 65228060Sbapt 66228060Sbapt assert (*n - nchars_avail == (size_t) (read_pos - *lineptr)); 67228060Sbapt if (nchars_avail < 2) 68228060Sbapt { 69228060Sbapt if (*n > MIN_CHUNK) 70228060Sbapt *n *= 2; 71228060Sbapt else 72228060Sbapt *n += MIN_CHUNK; 73228060Sbapt 74228060Sbapt nchars_avail = *n + *lineptr - read_pos; 75228060Sbapt char *new_line = new char[*n]; 76228060Sbapt if (*lineptr) 77228060Sbapt { 78228060Sbapt memcpy (new_line, *lineptr, read_pos - *lineptr); 79228060Sbapt delete[] *lineptr; 80228060Sbapt } 81228060Sbapt *lineptr = new_line; 82228060Sbapt read_pos = *n - nchars_avail + *lineptr; 83228060Sbapt assert (*n - nchars_avail == (size_t) (read_pos - *lineptr)); 84228060Sbapt } 85228060Sbapt 86228060Sbapt if (c == EOF || ferror (stream)) 87228060Sbapt { 88228060Sbapt /* Return partial line, if any. */ 89228060Sbapt if (read_pos == *lineptr) 90228060Sbapt return -1; 91228060Sbapt else 92228060Sbapt break; 93228060Sbapt } 94228060Sbapt 95228060Sbapt *read_pos++ = c; 96228060Sbapt nchars_avail--; 97228060Sbapt 98228060Sbapt if (c == terminator) 99228060Sbapt /* Return the line. */ 100228060Sbapt break; 101228060Sbapt } 102228060Sbapt 103228060Sbapt /* Done - NUL terminate and return the number of chars read. */ 104228060Sbapt *read_pos = '\0'; 105228060Sbapt 106228060Sbapt return read_pos - (*lineptr + offset); 107228060Sbapt} 108228060Sbapt 109228060Sbaptint 110228060Sbaptget_line (char **lineptr, size_t *n, FILE *stream) 111228060Sbapt{ 112228060Sbapt return getstr (lineptr, n, stream, '\n', 0); 113228060Sbapt} 114228060Sbapt 115228060Sbaptint 116228060Sbaptget_delim (char **lineptr, size_t *n, int delimiter, FILE *stream) 117228060Sbapt{ 118228060Sbapt return getstr (lineptr, n, stream, delimiter, 0); 119228060Sbapt} 120