Blame lib/linebuffer.c

Packit Service 2723c6
/* linebuffer.c -- read arbitrarily long lines
Packit Service 2723c6
Packit Service 2723c6
   Copyright (C) 1986, 1991, 1998-1999, 2001, 2003-2004, 2006-2007, 2009-2018
Packit Service 2723c6
   Free Software Foundation, Inc.
Packit Service 2723c6
Packit Service 2723c6
   This program is free software: you can redistribute it and/or modify
Packit Service 2723c6
   it under the terms of the GNU General Public License as published by
Packit Service 2723c6
   the Free Software Foundation; either version 3 of the License, or
Packit Service 2723c6
   (at your option) any later version.
Packit Service 2723c6
Packit Service 2723c6
   This program is distributed in the hope that it will be useful,
Packit Service 2723c6
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2723c6
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 2723c6
   GNU General Public License for more details.
Packit Service 2723c6
Packit Service 2723c6
   You should have received a copy of the GNU General Public License
Packit Service 2723c6
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit Service 2723c6
Packit Service 2723c6
/* Written by Richard Stallman. */
Packit Service 2723c6
Packit Service 2723c6
#include <config.h>
Packit Service 2723c6
Packit Service 2723c6
#include <stdio.h>
Packit Service 2723c6
#include <stdlib.h>
Packit Service 2723c6
#include <string.h>
Packit Service 2723c6
#include <sys/types.h>
Packit Service 2723c6
#include "linebuffer.h"
Packit Service 2723c6
#include "xalloc.h"
Packit Service 2723c6
Packit Service 2723c6
#if USE_UNLOCKED_IO
Packit Service 2723c6
# include "unlocked-io.h"
Packit Service 2723c6
#endif
Packit Service 2723c6
Packit Service 2723c6
/* Initialize linebuffer LINEBUFFER for use. */
Packit Service 2723c6
Packit Service 2723c6
void
Packit Service 2723c6
initbuffer (struct linebuffer *linebuffer)
Packit Service 2723c6
{
Packit Service 2723c6
  memset (linebuffer, 0, sizeof *linebuffer);
Packit Service 2723c6
}
Packit Service 2723c6
Packit Service 2723c6
struct linebuffer *
Packit Service 2723c6
readlinebuffer (struct linebuffer *linebuffer, FILE *stream)
Packit Service 2723c6
{
Packit Service 2723c6
  return readlinebuffer_delim (linebuffer, stream, '\n');
Packit Service 2723c6
}
Packit Service 2723c6
Packit Service 2723c6
/* Read an arbitrarily long line of text from STREAM into LINEBUFFER.
Packit Service 2723c6
   Consider lines to be terminated by DELIMITER.
Packit Service 2723c6
   Keep the delimiter; append DELIMITER if it's the last line of a file
Packit Service 2723c6
   that ends in a character other than DELIMITER.  Do not NUL-terminate.
Packit Service 2723c6
   Therefore the stream can contain NUL bytes, and the length
Packit Service 2723c6
   (including the delimiter) is returned in linebuffer->length.
Packit Service 2723c6
   Return NULL when stream is empty.  Return NULL and set errno upon
Packit Service 2723c6
   error; callers can distinguish this case from the empty case by
Packit Service 2723c6
   invoking ferror (stream).
Packit Service 2723c6
   Otherwise, return LINEBUFFER.  */
Packit Service 2723c6
struct linebuffer *
Packit Service 2723c6
readlinebuffer_delim (struct linebuffer *linebuffer, FILE *stream,
Packit Service 2723c6
                      char delimiter)
Packit Service 2723c6
{
Packit Service 2723c6
  int c;
Packit Service 2723c6
  char *buffer = linebuffer->buffer;
Packit Service 2723c6
  char *p = linebuffer->buffer;
Packit Service 2723c6
  char *end = buffer + linebuffer->size; /* Sentinel. */
Packit Service 2723c6
Packit Service 2723c6
  if (feof (stream))
Packit Service 2723c6
    return NULL;
Packit Service 2723c6
Packit Service 2723c6
  do
Packit Service 2723c6
    {
Packit Service 2723c6
      c = getc (stream);
Packit Service 2723c6
      if (c == EOF)
Packit Service 2723c6
        {
Packit Service 2723c6
          if (p == buffer || ferror (stream))
Packit Service 2723c6
            return NULL;
Packit Service 2723c6
          if (p[-1] == delimiter)
Packit Service 2723c6
            break;
Packit Service 2723c6
          c = delimiter;
Packit Service 2723c6
        }
Packit Service 2723c6
      if (p == end)
Packit Service 2723c6
        {
Packit Service 2723c6
          size_t oldsize = linebuffer->size;
Packit Service 2723c6
          buffer = x2realloc (buffer, &linebuffer->size);
Packit Service 2723c6
          p = buffer + oldsize;
Packit Service 2723c6
          linebuffer->buffer = buffer;
Packit Service 2723c6
          end = buffer + linebuffer->size;
Packit Service 2723c6
        }
Packit Service 2723c6
      *p++ = c;
Packit Service 2723c6
    }
Packit Service 2723c6
  while (c != delimiter);
Packit Service 2723c6
Packit Service 2723c6
  linebuffer->length = p - buffer;
Packit Service 2723c6
  return linebuffer;
Packit Service 2723c6
}
Packit Service 2723c6
Packit Service 2723c6
/* Free the buffer that was allocated for linebuffer LINEBUFFER.  */
Packit Service 2723c6
Packit Service 2723c6
void
Packit Service 2723c6
freebuffer (struct linebuffer *linebuffer)
Packit Service 2723c6
{
Packit Service 2723c6
  free (linebuffer->buffer);
Packit Service 2723c6
}