#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "buffer.h"
#include "line.h"
#include "unfold.h"
#include "misc.h"
unfold_t *unfold_alloc(void)
{
unfold_t *u = NULL;
u = (unfold_t *)malloc(sizeof(unfold_t));
if (u == NULL)
return NULL;
memset((unfold_t *)u, 0, sizeof(unfold_t));
return u;
}
unfold_t *unfold_init(int fd, unsigned long blen)
{
int ret = 0;
unfold_t *u = NULL;
u = unfold_alloc();
if (u == NULL)
return NULL;
u->b = buffer_init(fd, blen);
if (u->b == NULL) {
unfold_kill(u);
return NULL;
}
u->l = line_alloc();
if (u->l == NULL) {
unfold_kill(u);
return NULL;
}
ret = line_init(u->l, NULL, blen);
if (!ret) {
unfold_kill(u);
return NULL;
}
u->lb = line_alloc();
if (u->lb == NULL) {
unfold_kill(u);
return NULL;
}
ret = line_init(u->lb, NULL, blen);
if (!ret) {
unfold_kill(u);
return NULL;
}
return u;
}
void unfold_kill(unfold_t *u)
{
if (!u)
return;
if (u->b)
buffer_kill(u->b);
if (u->l)
line_kill(u->l);
if (u->lb)
line_kill(u->lb);
free(u);
}
void unfold_restart(unfold_t *u, int fd)
{
u->eof = 0;
line_restart(u->l);
line_restart(u->lb);
buffer_restart(u->b, fd);
}
char *unfold_next_line(unfold_t *u)
{
int ret = 0;
char *p = NULL;
if (u->eof)
return NULL;
if (u->l->bytes)
line_restart(u->l);
/*
Any saved data goes into the main buffer
*/
if (u->lb->bytes) {
ret = line_inject(u->l, u->lb->data, u->lb->bytes);
if (!ret) {
u->eof = 1;
return NULL;
}
/*
..and the saving buffer gets restarted
*/
line_restart(u->lb);
}
while(1) {
p = buffer_next_line(u->b);
if (p == NULL) {
if (u->l->bytes) {
u->eof = 1;
return u->l->data;
}
return NULL;
}
/*
Blank lines end the unfold
*/
if (!(*p)) {
if (u->l->bytes) {
u->eof = 1;
return u->l->data;
}
return NULL;
}
/*
Rolled lines always get appended
*/
if ((*p == ' ') || (*p == '\t')) {
#ifdef DEBUG
printf("ROLLING: [%s]\n", (p + 1));
#endif
ret = line_inject(u->l, (p + 1), (u->b->l->bytes - 1));
if (!ret) {
u->eof = 1;
return NULL;
}
continue;
}
/*
If we have data already in the line buffer,
we need to back up the line we just read,
and return the current data.
*/
if (u->l->bytes) {
#ifdef DEBUG
printf("SAVING: [%s]\n", p);
#endif
ret = line_inject(u->lb, p, u->b->l->bytes);
if (!ret) {
u->eof = 1;
return NULL;
}
return u->l->data;
}
/*
Otherwise just inject into the buffer and continue
*/
#ifdef DEBUG
printf("INJECTING: [%s]\n", p);
#endif
ret = line_inject(u->l, p, u->b->l->bytes);
if (!ret) {
u->eof = 1;
return NULL;
}
}
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1