
#include <errno.h>
#include <string.h>
#include <unistd.h>

#include "LineReader.h"


const char BS = 8, LF = '\n', CR = '\r';

LineReader::LineReader(int fd)
{
	cursor = 0;
	eob = 0;
	eof = 0;
	eol = 0;
	this->fd = fd;
}

int LineReader::available()
{
	while (eol < eob
		&& buf[eol] != BS
		&& buf[eol] != CR
		&& buf[eol] != LF)
		eol++;
	return eol < eob || eol == bufSize;
}

const char *LineReader::next()
{
	while (!available() && !eof)
		read();

	if (eob == 0)
		return NULL;

	for (int i = 0; i < eol; i++)
		line[cursor++] = buf[i];
	line[cursor] = 0;

	// go to the first character of the next line
	int next = eol;
	if (next == eob || buf[next] != BS)
	{
		cursor = 0;
		if (next + 1 < eob && buf[next + 1] == LF)
			next++;
		if (next < eob)
			next++;
	}
	else
	{
		for (; next < eob && buf[next] == BS; next++)
			if (cursor > 0)
				cursor--;
	}

//	for (int j = 0; j < eob - next; j++)
//		buf[j] = buf[j + next];
	memmove(buf, buf + next, eob - next);
	eob -= next;
	eol = 0;

	return line;
}

void LineReader::read()
{
	int n;
	while ((n = ::read(fd, &buf[eob], bufSize - eob)) == -1
		&& errno == EINTR)
		;

	if (n == 0)
		eof = 1;
	else
	if (n > 0)
		eob += n;
}
