/*
 * Simple, sorted list.
 */

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "fdlist.h"

bool fdlist_new(fdlist_t* fdlist, int max)
{
	memset(fdlist,0,sizeof(fdlist_t));
	
	fdlist->list = 
		(fdlist_node_t*) malloc( max * sizeof(fdlist_node_t) );
	if (fdlist->list == NULL) {
		fprintf(stderr, 
			"ERROR: malloc failed, errno: %d, %s",
			errno, strerror(errno));
		return false;
	}
	memset(fdlist->list, 0, max * sizeof(fdlist_node_t) );
	fdlist->max = max;
	return true;
}

void fdlist_destroy (fdlist_t* fdlist) {
	int pos;
	for ( pos=0; pos < fdlist->num; pos++) {
		free(fdlist->list[pos].buffer);
	}
	free(fdlist->list);
	fdlist->max=0;
	fdlist->num=0;
}

int fdlist_find_pos(fdlist_t* fdlist, int fd) {
	int s,e,pos;
	s = 0;
	e = fdlist->num;
	while ( (e-s) > 0 ) {
		pos = ( s + e ) / 2;
		if ( fdlist->list[pos].fd == fd ) {
			return pos;
		} if ( fdlist->list[pos].fd > fd ) {
			e=pos;
		} else {
			s=pos+1;
		}
	}
	return -1;
}

fdlist_node_t* fdlist_find(fdlist_t* fdlist, int fd) {
	int pos = fdlist_find_pos (fdlist, fd);
	if (pos < 0) {
		return NULL;
	}
	return (fdlist->list + pos);
}

fdlist_node_t* fdlist_add(fdlist_t* fdlist, int fd, pid_t pid) {
	int pos;
	if ( (fdlist->num+1) > fdlist->max ) {
		fprintf(stderr,"ERROR: no space left in the list");
		return NULL;
	}
	pos = fdlist->num;
	/*
	 * move things to make place, hopefully pids increase.
	 */
	while( (pos > 0) && (fdlist->list[pos-1].fd > fd)) {
		fdlist->list[pos].fd=fdlist->list[pos-1].fd;
		fdlist->list[pos].pid=fdlist->list[pos-1].pid;
		fdlist->list[pos].open=fdlist->list[pos-1].open;
		fdlist->list[pos].buffer=fdlist->list[pos-1].buffer;
		fdlist->list[pos].n=fdlist->list[pos-1].n;
		fdlist->list[pos].size=fdlist->list[pos-1].size;

		pos--;
	}
	fdlist->num++;
	fdlist->list[pos].fd=fd;
	fdlist->list[pos].pid=pid;
	fdlist->list[pos].open = true;
	return (fdlist->list + pos);
}

void fdlist_delete(fdlist_t* fdlist, int fd) {
	int pos=fdlist_find_pos(fdlist, fd);
	if (pos < 0) {
		fprintf(stderr, 
			"ERROR: trying to remove a nonexisting element");
		return;
	}
	free(fdlist->list[pos].buffer);
	fdlist->num--;
	while ( pos < fdlist->num ) {
		fdlist->list[pos].fd=fdlist->list[pos+1].fd;
		fdlist->list[pos].pid=fdlist->list[pos+1].pid;
		fdlist->list[pos].open=fdlist->list[pos+1].open;
		fdlist->list[pos].buffer=fdlist->list[pos+1].buffer;
		fdlist->list[pos].n=fdlist->list[pos+1].n;
		fdlist->list[pos].size=fdlist->list[pos+1].size;
		
		pos++;
	}
}


