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

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

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

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

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

pidlist_node_t* pidlist_find(pidlist_t* pidlist, pid_t pid) {
	int pos = pidlist_find_pos (pidlist, pid);
	if (pos < 0) {
		return NULL;
	}
	return (pidlist->list + pos);
}

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

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

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


