Skip to content
getline.c 1.7 KiB
Newer Older
Seblu's avatar
Seblu committed
/*
Seblu's avatar
Seblu committed
** getline.c for 42sh
Seblu's avatar
Seblu committed
**
** Made by Seblu
** Login   <seblu@epita.fr>
**
** Started on  Wed Aug  2 01:25:01 2006 Seblu
Seblu's avatar
Seblu committed
** Last update Tue Aug 29 02:20:32 2006 Seblu
Seblu's avatar
Seblu committed
*/

Seblu's avatar
Seblu committed
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
Seblu's avatar
Seblu committed
#include "../common/macro.h"
Seblu's avatar
Seblu committed
#include "getline.h"
Seblu's avatar
Seblu committed

/*!
** Secure layer over strlen
**
** @param s the string
**
** @return lenght of the string
*/
Seblu's avatar
Seblu committed
#define sstrlen(s) ((s) == NULL ? 0 : strlen(s))
Seblu's avatar
Seblu committed

/*
** Append a string to the buffer string
*/
Seblu's avatar
Seblu committed
static void     buf_str(char **str, char *append, unsigned n)
Seblu's avatar
Seblu committed
{
  unsigned      ln;
  unsigned      i;
  unsigned      j;

Seblu's avatar
Seblu committed
  ln = sstrlen(*str);
Seblu's avatar
Seblu committed
  if ((*str = realloc(*str, (ln + n + 1) * sizeof (char))) == NULL)
    exit(1);
  for (i = ln, j = 0; i < ln + n; i++, j++)
    (*str)[i] = append[j];
  (*str)[ln + n] = 0;
}

Seblu's avatar
Seblu committed
s_getline		*getline_open(int fd)
Seblu's avatar
Seblu committed
{
Seblu's avatar
Seblu committed
  s_getline		*new_buf;
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
  secmalloc(new_buf, sizeof (s_getline));
Seblu's avatar
Seblu committed
  new_buf->fd = fd;
  new_buf->size = 0;
  new_buf->offset = 0;
  return new_buf;
}

Seblu's avatar
Seblu committed
void            getline_close(s_getline *buf, int closefd)
Seblu's avatar
Seblu committed
{
  if (closefd)
    close(buf->fd);
  free(buf);
}

Seblu's avatar
Seblu committed
char            *getline(s_getline *buf)
Seblu's avatar
Seblu committed
{
  char          *string = NULL;
  int           i;

  do
  {
    for (i = buf->offset; i < buf->size; i++)
      {
        if (buf->data[i] == '\n')
          {
Seblu's avatar
Seblu committed
            buf_str(&string, buf->data + buf->offset, i - buf->offset + 1);
Seblu's avatar
Seblu committed
            buf->offset = i + 1;
            return string;
          }
      }
    if (buf->size - buf->offset > 0)
Seblu's avatar
Seblu committed
      buf_str(&string, buf->data + buf->offset, buf->size - buf->offset);
Seblu's avatar
Seblu committed
    buf->offset = 0;
Seblu's avatar
Seblu committed
    buf->size = read(buf->fd, buf->data, GETLINE_BUF_SIZE);
Seblu's avatar
Seblu committed
    if (buf->size < 0)
      buf->size = 0;
  }
  while (buf->size > 0);
  return string;
}