Mercurial > repos > rhope
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; +}