/*
 * Simple, static size, sorted list.
 */

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

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

void slist_destroy (slist_t* slist) {
	int pos;
	for ( pos=0; pos < slist->num; pos++) {
		free(slist->list[pos].name);
	}
	free(slist->list);
	slist->max=0;
	slist->num=0;
}

int slist_find_pos(slist_t* slist, pid_t pid) {
	int s,e,pos;
	s = 0;
	e = slist->num;
	while ( (e-s) > 0 ) {
		pos = ( s + e ) / 2;
		if ( slist->list[pos].pid == pid ) {
			return pos;
		} if ( slist->list[pos].pid > pid ) {
			e=pos;
		} else {
			s=pos+1;
		}
	}
	return -1;
}

slist_node_t* slist_find(slist_t* slist, pid_t pid) {
	int pos = slist_find_pos (slist, pid);
	if (pos < 0) {
		return NULL;
	}
	return (slist->list + pos);
}

slist_node_t* slist_add(slist_t* slist, pid_t pid, char* name) {
	int pos;
	if ( (slist->num+1) > slist->max ) {
		fprintf(stderr,"ERROR: no space left in the list");
		return NULL;
	}
	pos = slist->num;
	/*
	 * move things to make place, hopefully pids increase.
	 */
	while( (pos > 0) && (slist->list[pos-1].pid > pid)) {
		slist->list[pos].pid=slist->list[pos-1].pid;
		slist->list[pos].name=slist->list[pos-1].name;
		slist->list[pos].outfd=slist->list[pos-1].outfd;
		slist->list[pos].errfd=slist->list[pos-1].errfd;
		slist->list[pos].output=slist->list[pos-1].output;
		slist->list[pos].error=slist->list[pos-1].error;

		pos--;
	}
	slist->num++;
	slist->list[pos].pid=pid;
	slist->list[pos].name=strdup(name);
	return (slist->list + slist->num);
}

void slist_delete(slist_t* slist, pid_t pid) {
	int pos=slist_find_pos(slist, pid);
	if (pos < 0) {
		fprintf(stderr, 
			"ERROR: trying to remove a nonexisting element");
		return;
	}
	free(slist->list[pos].name);
	slist->num--;
	while ( pos < slist->num ) {
		slist->list[pos].pid=slist->list[pos+1].pid;
		slist->list[pos].name=slist->list[pos+1].name;
		slist->list[pos].outfd=slist->list[pos+1].outfd;
		slist->list[pos].errfd=slist->list[pos+1].errfd;
		slist->list[pos].output=slist->list[pos+1].output;
		slist->list[pos].error=slist->list[pos+1].error;
		
		pos++;
	}
}


