/*
 * @(#)BufferedReader.cpp
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2002 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDWserver.cpp for details.
 *
 * Jörg Haeger, 17.04.2002
 */

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include "BufferedReader.h"

BufferedReader::BufferedReader(int fd, int size) {
	this->fd = fd;
	buf = new char[size];
	this->size = size;
	count = 0;
	pos = 0;
	markpos = -1;
	marklimit = 0;
}

BufferedReader::~BufferedReader() {
	delete[] buf;
}

void BufferedReader::mark(int readAheadLimit) {
	if (readAheadLimit + 1024 > size) {
		char *oldBuf = buf;
		buf = new char[readAheadLimit + 1024];
		size = readAheadLimit + 1024;
		memcpy(buf, oldBuf, count);
		delete[] oldBuf;
	}
	markpos = pos;
	marklimit = readAheadLimit;
}

int BufferedReader::read() {
	if (pos < count)
		return buf[pos++];

	if (markpos < 0 || pos - markpos > marklimit) {
		count = 0;
		pos = 0;
		markpos = -1;
	}
	else if (markpos > 0) {
		memmove(buf, buf + markpos, count - markpos);
		count -= markpos;
		pos -= markpos;
		markpos = 0;
	}

	int n;
	while ((n = ::read(fd, &buf[count], size - count)) == -1
		&& errno == EINTR)
		;

	if (n <= 0)
		return -1;

	count += n;

	return buf[pos++];
}

int BufferedReader::ready(int timeout) {
	if (pos < count)
		return 1;

	fd_set fdSet;
	FD_ZERO(&fdSet);
	FD_SET(fd, &fdSet);
	struct timeval tv;
	tv.tv_sec = timeout / 1000;
	tv.tv_usec = 1000 * (timeout % 1000);
	return select(FD_SETSIZE, &fdSet, NULL, NULL, &tv) != 0;
}

void BufferedReader::reset() {
	if (markpos >= 0)
		if (pos - markpos > marklimit)
			markpos = -1;
		else
			pos = markpos;
}
