diff list.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/list.c	Tue Apr 28 23:06:07 2009 +0000
@@ -0,0 +1,290 @@
+#include "structs.h"
+#include "datum.h"
+#include "interp.h"
+#include <stdlib.h>
+#include <string.h>
+
+datum * create_list(program * prog)
+{
+	short i;
+	datum * dat = new_datum(BUILTIN_TYPE_LIST, 1, sizeof(list_data) + sizeof(datum *)*7, prog);
+	dat->c.generic.len = 8;
+	((list_data *)dat->c.generic.data)->num_entries = 0;
+	return dat;
+}
+
+int vis_list_new(datum ** inputlist, queue_entry * worker_entry)
+{
+	inputlist[0] = create_list(worker_entry->instance->def->program);
+	return 0;
+}
+
+int vis_list_append(datum ** inputlist, queue_entry * worker_entry)
+{
+	int ref_count, new_entry_count;
+	list_data * list, * new_list;
+	datum * output;
+	int i;
+	
+	VIS_EnterCriticalSection(inputlist[0]->lock);
+		ref_count = inputlist[0]->ref_count;
+	VIS_LeaveCriticalSection(inputlist[0]->lock);
+	list = ((list_data *)inputlist[0]->c.generic.data);
+	DEBUGPRINTF("append: generic.len = %d, list->num_entries = %d, ref_count = %d\n", inputlist[0]->c.generic.len, list->num_entries, ref_count);
+	if(ref_count == 1)
+	{
+		if(inputlist[0]->c.generic.len > list->num_entries)
+		{
+			DEBUGPUTS("Fast append\n");
+			list->entries[list->num_entries] = inputlist[1]; //No need to add_ref because we're consuming the ref we wer passed
+			++(list->num_entries);
+		}
+		else
+		{
+			DEBUGPUTS("malloc append\n");
+			new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
+			new_list = malloc((new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
+			new_list->num_entries = list->num_entries+1;
+			inputlist[0]->c.generic.len = new_entry_count;
+			memcpy(new_list->entries, list->entries, list->num_entries * sizeof(datum *));
+			new_list->entries[list->num_entries] = inputlist[1];
+			inputlist[0]->c.generic.data = new_list;
+			VIS_FREE(list, "List object");
+		}
+	}
+	else
+	{
+		DEBUGPUTS("datum copy append\n");
+		
+		if(inputlist[0]->c.generic.len > list->num_entries)
+			new_entry_count = inputlist[0]->c.generic.len;
+		else
+			new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
+		output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
+		new_list = output->c.generic.data;
+		new_list->num_entries = list->num_entries+1;
+		output->c.generic.len = new_entry_count;
+		for(i = 0; i < list->num_entries; ++i)
+			new_list->entries[i] = add_ref(list->entries[i]);
+		new_list->entries[list->num_entries] = inputlist[1];
+		release_ref(inputlist[0]);
+		inputlist[0] = output;
+	}
+	DEBUGPRINTF("append: generic.len = %d, list->num_entries = %d\n", inputlist[0]->c.generic.len, ((list_data *)inputlist[0]->c.generic.data)->num_entries);
+	return 0;
+}
+
+int vis_list_swap(datum ** inputlist, queue_entry * worker_entry)
+{
+	//TODO: Throw error if indices out of bounds
+	list_data * list;
+	datum * temp;
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	list = ((list_data *)inputlist[0]->c.generic.data);
+
+	temp = list->entries[inputlist[1]->c.integers.num_a];
+	list->entries[inputlist[1]->c.integers.num_a] = list->entries[inputlist[2]->c.integers.num_a];
+	list->entries[inputlist[2]->c.integers.num_a] = temp;
+	release_ref(inputlist[1]);
+	release_ref(inputlist[2]);
+	return 0;
+}
+
+int vis_list_index(datum ** inputlist, queue_entry * worker_entry)
+{
+	//TODO: Throw error if indices out of bounds
+	list_data * list = ((list_data *)inputlist[0]->c.generic.data);
+	datum * output;
+	DEBUGPRINTF("index: generic.len = %d, list->num_entries = %d, requested index: %d\n", inputlist[0]->c.generic.len, list->num_entries, inputlist[1]->c.integers.num_a);
+	DEBUGPRINTF("list->entries[%d] = %X\n", inputlist[1]->c.integers.num_a, list->entries[inputlist[1]->c.integers.num_a]);
+	if(inputlist[1]->c.integers.num_a < list->num_entries && list->entries[inputlist[1]->c.integers.num_a])
+	{
+		output = add_ref(list->entries[inputlist[1]->c.integers.num_a]);
+		release_ref(inputlist[1]);
+		inputlist[1] = NULL;
+	}
+	else
+	{
+		output = NULL;
+		inputlist[1] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+		inputlist[1]->c.integers.num_a = 0;
+	}
+	
+	release_ref(inputlist[0]);
+	inputlist[0] = output;
+	return 0;
+}
+
+int vis_list_insert(datum ** inputlist, queue_entry * worker_entry)
+{
+	int ref_count, new_entry_count;
+	list_data * list, * new_list;
+	datum * output;
+	int i;
+	VIS_EnterCriticalSection(inputlist[0]->lock);
+		ref_count = inputlist[0]->ref_count;
+	VIS_LeaveCriticalSection(inputlist[0]->lock);
+	list = ((list_data *)inputlist[0]->c.generic.data);
+	if(ref_count == 1)
+	{
+		if(inputlist[0]->c.generic.len > list->num_entries)
+		{
+			memmove(list->entries + inputlist[1]->c.integers.num_a + 1, list->entries + inputlist[1]->c.integers.num_a, sizeof(datum *) * (list->num_entries-inputlist[1]->c.integers.num_a));
+			list->entries[inputlist[1]->c.integers.num_a] = inputlist[2]; //No need to add_ref because we're consuming the ref we wer passed
+			++(list->num_entries);
+		}
+		else
+		{
+			new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
+			new_list = malloc((new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
+			new_list->num_entries = list->num_entries+1;
+			inputlist[0]->c.generic.len = new_entry_count;
+			memcpy(new_list->entries, list->entries, list->num_entries * sizeof(datum *));
+			new_list->entries[list->num_entries] = inputlist[1];
+			inputlist[0]->c.generic.data = new_list;
+			VIS_FREE(list, "List object");
+		}
+	}
+	else
+	{
+		new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
+		output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
+		new_list = output->c.generic.data;
+		new_list->num_entries = list->num_entries+1;
+		output->c.generic.len = new_entry_count;
+		for(i = 0; i < inputlist[1]->c.integers.num_a; ++i)
+			new_list->entries[i] = add_ref(list->entries[i]);
+		for(i = inputlist[1]->c.integers.num_a; i < list->num_entries; ++i)
+			new_list->entries[i+1] = add_ref(list->entries[i]);
+		release_ref(inputlist[0]);
+		new_list->entries[list->num_entries] = inputlist[2];
+		inputlist[0] = output;
+	}
+	release_ref(inputlist[1]);
+	return 0;
+}
+
+int vis_list_remove(datum ** inputlist, queue_entry * worker_entry)
+{
+	int ref_count, new_entry_count;
+	list_data * list, * new_list;
+	int i;
+	datum * output;
+	VIS_EnterCriticalSection(inputlist[0]->lock);
+		ref_count = inputlist[0]->ref_count;
+	VIS_LeaveCriticalSection(inputlist[0]->lock);
+	list = ((list_data *)inputlist[0]->c.generic.data);
+	if(ref_count == 1)
+	{
+		release_ref(list->entries[inputlist[1]->c.integers.num_a]);
+		memmove(list->entries + inputlist[1]->c.integers.num_a, list->entries + inputlist[1]->c.integers.num_a + 1, sizeof(datum *) * (list->num_entries-(inputlist[1]->c.integers.num_a+1)));
+		--(list->num_entries);
+	}
+	else
+	{
+		new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size
+		output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data));
+		new_list = output->c.generic.data;
+		new_list->num_entries = list->num_entries+1;
+		output->c.generic.len = new_entry_count;
+		for(i = 0; i < inputlist[1]->c.integers.num_a; ++i)
+			new_list->entries[i] = add_ref(list->entries[i]);
+		for(i = inputlist[1]->c.integers.num_a+1; i < list->num_entries; ++i)
+			new_list->entries[i-1] = add_ref(list->entries[i]);
+		release_ref(inputlist[0]);
+		inputlist[0] = output;
+	}
+	release_ref(inputlist[1]);
+	return 0;
+}
+
+int vis_list_set(datum ** inputlist, queue_entry * worker_entry)
+{
+	int new_num_entries, new_generic_len, i;
+	list_data * list;
+	DEBUGPUTS("vis_list_set\n");
+	if(((list_data *)inputlist[0]->c.generic.data)->num_entries <= inputlist[1]->c.integers.num_a)
+	{
+		new_num_entries = inputlist[1]->c.integers.num_a + 1;
+		new_generic_len = (new_num_entries + (new_num_entries>>1)-1)*sizeof(datum*) + sizeof(list_data);
+	}
+	else 
+	{
+		new_num_entries = ((list_data *)inputlist[0]->c.generic.data)->num_entries;
+		new_generic_len = 0;
+	}
+	DEBUGPRINTF("new_generic_len: %d, new num_entries: %d\n", new_generic_len, new_num_entries);
+	inputlist[0] = copy_datum(inputlist[0], new_generic_len);
+	if(new_generic_len) {
+		inputlist[0]->c.generic.len = (new_num_entries + (new_num_entries>>1));
+	}
+	DEBUGPUTS("Datum copy done\n");
+	list = ((list_data *)inputlist[0]->c.generic.data);
+	DEBUGPUTS("before Null fill loop\n");
+	for(i = list->num_entries; i < new_num_entries; ++i)
+		list->entries[i] = NULL;
+	DEBUGPUTS("Before existing entry release_ref\n");
+	if(inputlist[1]->c.integers.num_a < list->num_entries)
+		release_ref(list->entries[inputlist[1]->c.integers.num_a]);
+	DEBUGPRINTF("Setting index %d to %X\n", inputlist[1]->c.integers.num_a, inputlist[2]);
+	list->entries[inputlist[1]->c.integers.num_a] = inputlist[2];
+	release_ref(inputlist[1]);
+	list->num_entries = new_num_entries;
+	DEBUGPUTS("vis_list_set done\n");
+	return 0;
+
+}
+
+int vis_list_length(datum ** inputlist, queue_entry * worker_entry)
+{
+	datum * output;
+	list_data * list = ((list_data *)inputlist[0]->c.generic.data);
+	output = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+	output->c.integers.num_a = list->num_entries;
+	release_ref(inputlist[0]);
+	inputlist[0] = output;
+	return 0;
+}
+
+int vis_list_first(datum ** inputlist, queue_entry * worker_entry)
+{
+	int i;
+	list_data * list = inputlist[0]->c.generic.data;
+	if(!list->num_entries)
+	{
+		inputlist[1] = inputlist[0];
+		inputlist[0] = NULL;
+	}
+	else
+	{
+		i = 0;
+		while(!list->entries[i] && i < list->num_entries)
+			++i;
+		release_ref(inputlist[0]);
+		inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+		inputlist[0]->c.integers.num_a = i;
+		inputlist[1] = NULL;
+	}
+	return 0;
+}
+
+int vis_list_next(datum ** inputlist, queue_entry * worker_entry)
+{
+	int i;
+	list_data * list = inputlist[0]->c.generic.data;
+	i = inputlist[1]->c.integers.num_a + 1;
+	while(i < list->num_entries && !list->entries[i])
+		++i;
+	if(i < list->num_entries)
+	{
+		release_ref(inputlist[0]);
+		inputlist[0] = copy_datum(inputlist[1], 0);
+		inputlist[1] = NULL;
+		inputlist[0]->c.integers.num_a = i;
+	} else {
+		release_ref(inputlist[1]);
+		inputlist[1] = inputlist[0];
+		inputlist[0] = NULL;
+	}
+	return 0;
+}