Skip to content
getln.c 1.92 KiB
Newer Older
Seblu's avatar
Seblu committed
/*
** getln.c for 42sh
**
** Made by Seblu
** Login   <seblu@epita.fr>
**
** Started on  Wed Aug  2 01:25:01 2006 Seblu
Seblu's avatar
Seblu committed
** Last update Thu Aug  3 11:44:30 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 "readline.h"

/*!
** Secure layer over strlen
**
** @param s the string
**
** @return lenght of the string
*/
Seblu's avatar
Seblu committed
static size_t         sstrlen(const char *s)
Seblu's avatar
Seblu committed
{
  if (s == NULL)
    return 0;
  return strlen(s);
}

/*
** 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;
}


/*
** Memory allocation of getln buffer
*/
struct s_getln          *getln_open(const int fd)
{
  struct s_getln        *new_buf;

  if ((new_buf = malloc(sizeof (struct s_getln))) == NULL)
    exit(1);
  new_buf->fd = fd;
  new_buf->size = 0;
  new_buf->offset = 0;
  return new_buf;
}

/*
** Free a getln struct
*/
void            getln_close(struct s_getln *buf, const int closefd)
{
  if (closefd)
    close(buf->fd);
  free(buf);
}

/*
** Get next line in a file
** Return NULL when nothing to read
*/
char            *getln(struct s_getln *buf)
{
  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;
    buf->size = read(buf->fd, buf->data, GETLN_BUF_SIZE);
    if (buf->size < 0)
      buf->size = 0;
  }
  while (buf->size > 0);
  return string;
}