diff file.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 94c885692eb5
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/file.c	Tue Apr 28 23:06:07 2009 +0000
@@ -0,0 +1,543 @@
+#include "structs.h"
+#include "datum.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int vis_file_from_string(datum ** inputlist, queue_entry * worker_entry)
+{
+	datum * output;
+	file_data * file;
+	output = new_datum(BUILTIN_TYPE_FILE, 1, sizeof(file_data), worker_entry->instance->def->program);
+	file = output->c.generic.data;
+	file->shared = malloc(sizeof(shared_file) + inputlist[0]->c.generic.len-1);
+	strcpy(file->shared->name, inputlist[0]->c.generic.data);
+	DEBUGPRINTF("File from string name: %s\n", file->shared->name);
+	release_ref(inputlist[0]);
+	file->shared->status = FILE_NOSIZE;
+	VIS_InitializeCriticalSection(file->shared->lock);
+	file->shared->ref_count = 1;
+	file->offset = 0;
+	inputlist[0] = output;
+	return 0;
+}
+
+void vis_file_read_open_check(file_data * file)
+{
+	switch(file->shared->status)
+	{
+		case FILE_NOSIZE:
+		case FILE_CLOSED:
+			DEBUGPUTS("File is closed, opening...\n");
+			DEBUGPRINTF("File name: %s\n", file->shared->name);
+			file->shared->file = fopen(file->shared->name, "rb");
+			if(!file->shared->file)
+			{
+				file->shared->status = FILE_CANT_OPEN;
+				file->shared->size = 0;
+				break;
+			}
+			if(file->shared->status == FILE_NOSIZE)
+			{
+				DEBUGPUTS("Getting file size.\n");
+				fseek(file->shared->file, 0, SEEK_END);
+				file->shared->size = ftell(file->shared->file);
+				DEBUGPRINTF("File size: %d.\n", file->shared->size);
+			}
+				
+			file->shared->status = FILE_READ;
+			break;
+		default://file is already open
+			break;
+	}
+	DEBUGPRINTF("Seeking to %d\n", file->offset);
+	if(file->shared->file)
+		fseek(file->shared->file, file->offset, SEEK_SET);
+	DEBUGPUTS("Done.\n");
+}
+
+int vis_file_get_fstring(datum ** inputlist, queue_entry * worker_entry)
+{
+	file_data * file;
+	datum * output = new_datum(BUILTIN_TYPE_STRING, 1, inputlist[1]->c.integers.num_a+1, worker_entry->instance->def->program);
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	if(inputlist[1]->c.integers.num_a > 0)
+	{
+		file = (file_data *)inputlist[0]->c.generic.data;
+		VIS_EnterCriticalSection(file->shared->lock);
+			vis_file_read_open_check(file);
+			fread(output->c.generic.data,1,inputlist[1]->c.integers.num_a, file->shared->file);
+		VIS_LeaveCriticalSection(file->shared->lock);
+		file->offset += inputlist[1]->c.integers.num_a;
+	}
+	((char *)output->c.generic.data)[inputlist[1]->c.integers.num_a] = '\0';
+	release_ref(inputlist[1]);
+	inputlist[1] = output;
+	return 0;
+}
+#define	FILE_SEARCH_BUFFER_SIZE	512
+
+typedef struct bufferlist
+{
+	char buffer[FILE_SEARCH_BUFFER_SIZE];
+	int index;
+	struct bufferlist * next;
+} bufferlist;
+
+int vis_file_get_dstring(datum ** inputlist, queue_entry * worker_entry)
+{
+	BOOL found = FALSE;
+	bufferlist buffers;
+	bufferlist * current, *temp,*temp2;
+	int i,j,k,startk;
+	int found_entry;
+	int string_offset;
+	int search_offset;
+	bufferlist * search_start;
+	int search_start_offset;
+	int *search_offsets;
+	bufferlist ** search_starts;
+	int *search_start_offsets;
+	int read_bytes;
+	
+	list_data * list;
+	file_data * file;
+	
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	file = (file_data *)inputlist[0]->c.generic.data;
+	buffers.next = NULL;
+	DEBUGPUTS("Entering critical section.\n");
+	VIS_EnterCriticalSection(file->shared->lock);
+		if(file->offset >= file->shared->size)
+		{
+	VIS_LeaveCriticalSection(file->shared->lock);
+			release_ref(inputlist[0]);
+			release_ref(inputlist[1]);
+			inputlist[0] = inputlist[1] = inputlist[2] = NULL;
+			inputlist[3] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+			datum_set_yesno(inputlist[3], 1);
+			return 0;
+		}
+		if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST)
+		{
+			
+			list = ((list_data *)inputlist[1]->c.generic.data);
+			DEBUGPRINTF("Delimeter input is a list with %d entries.\n", list->num_entries);
+			search_offsets = malloc(sizeof(int) * (list->num_entries));
+			DEBUGPRINTF("Allocated %d bytes.\n", sizeof(int) * (list->num_entries));
+			search_starts = malloc(sizeof(bufferlist *) * (list->num_entries));
+			DEBUGPRINTF("Allocated %d bytes.\n", sizeof(bufferlist *) * (list->num_entries));
+			search_start_offsets = malloc(sizeof(int) * (list->num_entries));
+			DEBUGPRINTF("Allocated %d bytes.\n", sizeof(int) * (list->num_entries));
+			for(i = 0; i < list->num_entries; ++i)
+			{
+				DEBUGPRINTF("Setting search_offsets[%d] = 0.\n", i);
+				search_offsets[i] = 0;
+			}
+		}
+		search_offset = 0;
+		current = &buffers;
+		current->index = 0;
+	
+		DEBUGPUTS("In critical section.\n");
+		vis_file_read_open_check(file);
+		DEBUGPUTS("File open.");
+		while(!found && !feof(file->shared->file))
+		{
+			DEBUGPRINTF("Reading %d bytes from file\n", FILE_SEARCH_BUFFER_SIZE);
+			read_bytes = fread(current->buffer, 1, FILE_SEARCH_BUFFER_SIZE, file->shared->file);
+			DEBUGPRINTF("fread read %d bytes\n", read_bytes);
+			for(i = 0; i < read_bytes && !found; ++i)
+			{
+				DEBUGPRINTF("Checking character #%d (%c)\n", i, current->buffer[i]);
+				switch(inputlist[1]->company->type_id)
+				{
+				case BUILTIN_TYPE_WHOLE:
+					if((int)current->buffer[i] == inputlist[1]->c.integers.num_a)
+					{
+						found = TRUE;
+						search_offset = 1;
+						search_start = current;
+						search_start_offset = i;
+					}
+					break;
+				case BUILTIN_TYPE_STRING:
+					if(current->buffer[i] == ((char *)inputlist[1]->c.generic.data)[search_offset])
+					{
+						if(search_offset == 0)
+						{
+							search_start = current;
+							search_start_offset = i;
+						}
+						++search_offset;
+						if(search_offset == (inputlist[1]->c.generic.len-1))
+							found = TRUE;
+					}
+					else
+					{
+						if(search_offset > 0)
+						{
+							current = search_start;
+							i = search_start_offset;
+						}
+						search_offset = 0;
+					}
+					break;
+				case BUILTIN_TYPE_LIST:
+					for(j = 0; j < list->num_entries; ++j)
+					{
+						DEBUGPRINTF("Testing list entry %d against character %d in buffer %d\n", j, i, current->index);
+						if(list->entries[j]->company->type_id == BUILTIN_TYPE_WHOLE && (int)current->buffer[i] == list->entries[j]->c.integers.num_a)
+						{
+							DEBUGPUTS("Matched whole number entry.\n");
+							found = TRUE;
+							found_entry = j;
+							search_offset = 1;
+							search_start = current;
+							search_start_offset = i;
+							break;
+						}
+						else if(list->entries[j]->company->type_id == BUILTIN_TYPE_STRING)
+						{
+							DEBUGPUTS("String entry.\n");
+							if(current->buffer[i] == ((char *)list->entries[j]->c.generic.data)[search_offsets[j]])
+							{
+								DEBUGPRINTF("%c in buffer matches character #%d in entry.\n", current->buffer[i], search_offsets[j]);
+								if(search_offsets[j] == 0)
+								{
+									search_starts[j] = current;
+									search_start_offsets[j] = i;
+								}
+								++search_offsets[j];
+								if(search_offsets[j] == (list->entries[j]->c.generic.len-1))
+								{
+									DEBUGPUTS("Entire string matched.\n");
+									found = TRUE;
+									found_entry = j;
+									search_offset = search_offsets[j];
+									search_start = search_starts[j];
+									search_start_offset = search_start_offsets[j];
+									break;
+								}
+							}
+							else if(search_offsets[j] > 0)
+							{
+								DEBUGPRINTF("%c in bufer does not match character #%d in entry.\n", current->buffer[i], search_offsets[j]);
+								temp = search_starts[j];
+								search_offsets[j] = 0;
+								startk = search_start_offsets[j];
+								while(temp && !found)
+								{
+									DEBUGPRINTF("Scanning block %d for possible missed match from %d to %d.\n", temp->index, startk, (temp == current ? i : FILE_SEARCH_BUFFER_SIZE)-1);
+									for(k = startk; k < (temp == current ? i : FILE_SEARCH_BUFFER_SIZE); ++k)
+									{
+										if(temp->buffer[k] == ((char *)list->entries[j]->c.generic.data)[search_offsets[j]])
+										{
+											if(!search_offsets[j])
+											{
+												search_starts[j] = temp;
+												search_start_offsets[j] = k;
+											}
+											++search_offsets[j];
+											if(search_offset == (list->entries[j]->c.generic.len-1))
+											{
+												found = TRUE;
+												found_entry = j;
+												search_start = search_starts[j];
+												search_start_offset = search_start_offsets[j];
+											}
+										}
+										else
+										{
+											if(search_offsets[j] > 0)
+											{
+												temp = search_starts[j];
+												k = search_start_offsets[j];
+											}
+											search_offsets[j] = 0;
+										}
+									}
+									startk = 0;
+									temp = temp->next;
+								}
+								
+							}
+							else
+								search_offsets[j] = 0;
+							
+						}
+					}
+					break;
+				}
+			}
+			if(!found && !feof(file->shared->file))
+			{
+				current->next = malloc(sizeof(bufferlist));
+				DEBUGPRINTF("Allocated next buffer at %X (%d bytes)\n", current->next, sizeof(bufferlist));
+				current->next->index = current->index+1;
+				current->next->next = NULL;
+				current = current->next;
+			}
+		}
+	VIS_LeaveCriticalSection(file->shared->lock);
+	if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST)
+	{
+		VIS_FREE(search_offsets, "Get DString@File, search offsets");
+		VIS_FREE(search_starts, "Get DString@File, search starts");
+		VIS_FREE(search_start_offsets, "Get DString@File, search start offsets");
+	}
+	if(found)
+	{
+		DEBUGPUTS("Found a delimeter");
+		if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST)
+		{
+			inputlist[2] = add_ref(list->entries[found_entry]);
+			release_ref(inputlist[1]);
+		}
+		else
+			inputlist[2] = inputlist[1];
+		inputlist[3] = NULL;
+	}
+	else
+	{
+		DEBUGPUTS("Didn't find a delimeter");
+		release_ref(inputlist[1]);
+		inputlist[2] = NULL;
+		inputlist[3] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+		datum_set_yesno(inputlist[3], 0);
+	}
+	//Does this need to be here still or was it just working around another bug?
+	if(search_start_offset < 0)
+		search_start_offset = 0;
+	if(!found) {
+		search_start = current;
+		search_start_offset = i;
+	}
+	if(found)
+	{
+		inputlist[1] = new_datum(BUILTIN_TYPE_STRING, 1, FILE_SEARCH_BUFFER_SIZE * current->index + search_start_offset+1, worker_entry->instance->def->program);
+		//file->offset += FILE_SEARCH_BUFFER_SIZE * current->index + search_start_offset + search_offset;
+		file->offset += FILE_SEARCH_BUFFER_SIZE * search_start->index + search_start_offset + search_offset;
+	}
+	else
+	{
+		inputlist[1] = new_datum(BUILTIN_TYPE_STRING, 1, FILE_SEARCH_BUFFER_SIZE * current->index + read_bytes+1, worker_entry->instance->def->program);
+		file->offset += FILE_SEARCH_BUFFER_SIZE * current->index + read_bytes;
+	}
+	temp = &buffers;
+	string_offset = 0;
+	while(temp)
+	{
+		DEBUGPRINTF("Copying from index %d to offset %X\n", temp->index, string_offset);
+		if(temp == search_start)
+		{
+			//if(found)
+			//{
+				temp->buffer[search_start_offset] = '\0';
+				memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, search_start_offset);
+				string_offset += search_start_offset;
+			/*}
+			else
+			{
+				memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, i);
+				string_offset += i;
+			}*/
+			break;
+		}
+		else
+		{
+			memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, FILE_SEARCH_BUFFER_SIZE);
+			string_offset += FILE_SEARCH_BUFFER_SIZE;
+		}
+		if(temp != &buffers)
+		{
+			temp2 = temp->next;
+			VIS_FREE(temp, "Get DString@File, buffer node");
+			temp = temp2;
+		}
+		else
+			temp = temp->next;
+	}
+	while(temp)
+	{
+		if(temp != &buffers)
+		{
+			temp2 = temp->next;
+			DEBUGPRINTF("Freeing %X\n", temp);
+			VIS_FREE(temp, "Get DString@File, buffer node");
+			temp = temp2;
+		}
+		else
+			temp = temp->next;
+	}
+	((char *)inputlist[1]->c.generic.data)[string_offset] = '\0';
+	DEBUGPRINTF("Output string: %s\n", inputlist[1]->c.generic.data);
+	return 0;
+}
+
+int vis_file_get_byte(datum ** inputlist, queue_entry * worker_entry)
+{
+	file_data * file;
+	BOOL eof;
+	char num;
+	
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	file = (file_data *)inputlist[0]->c.generic.data;
+	VIS_EnterCriticalSection(file->shared->lock);
+		if(!(eof = (file->offset >= file->shared->size)))
+		{
+			vis_file_read_open_check(file);
+			fread(&num,sizeof(char),1, file->shared->file);
+		}
+	VIS_LeaveCriticalSection(file->shared->lock);
+	if(eof)
+	{
+		release_ref(inputlist[0]);
+		inputlist[0] = inputlist[1] = NULL;
+		inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+		datum_set_yesno(inputlist[2], 1);
+	}
+	else
+	{
+		inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+		inputlist[1]->c.integers.num_a = num;
+		inputlist[2] = NULL;
+		file->offset += sizeof(char);
+	}
+	return 0;
+}
+
+int vis_file_get_word(datum ** inputlist, queue_entry * worker_entry)
+{
+	file_data * file;
+	BOOL eof;
+	short num;
+
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	file = (file_data *)inputlist[0]->c.generic.data;
+	VIS_EnterCriticalSection(file->shared->lock);
+		if(!(eof = (file->offset >= file->shared->size)))
+		{
+			vis_file_read_open_check(file);
+			fread(&num,sizeof(short),1, file->shared->file);
+		}
+	VIS_LeaveCriticalSection(file->shared->lock);
+	if(eof)
+	{
+		release_ref(inputlist[0]);
+		inputlist[0] = inputlist[1] = NULL;
+		inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+		datum_set_yesno(inputlist[2], 1);
+	}
+	else
+	{
+		inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+		inputlist[1]->c.integers.num_a = num;
+		inputlist[2] = NULL;
+		file->offset += sizeof(short);
+	}
+	return 0;
+}
+
+int vis_file_get_long(datum ** inputlist, queue_entry * worker_entry)
+{
+	file_data * file;
+	BOOL eof;
+	long num;
+	
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	file = (file_data *)inputlist[0]->c.generic.data;
+	VIS_EnterCriticalSection(file->shared->lock);
+		if(!(eof = (file->offset >= file->shared->size)))
+		{
+			vis_file_read_open_check(file);
+			fread(&num,sizeof(long),1, file->shared->file);
+		}
+	VIS_LeaveCriticalSection(file->shared->lock);
+	if(eof)
+	{
+		release_ref(inputlist[0]);
+		inputlist[0] = inputlist[1] = NULL;
+		inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+		datum_set_yesno(inputlist[2], 1);
+	}
+	else
+	{
+		inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+		inputlist[1]->c.integers.num_a = num;
+		inputlist[2] = NULL;
+		file->offset += sizeof(long);
+	}
+	return 0;
+}
+
+void vis_file_write_open_check(file_data * file)
+{
+	switch(file->shared->status)
+	{
+		case FILE_READ:
+			fclose(file->shared->file);
+		case FILE_NOSIZE:
+		case FILE_CLOSED:
+			DEBUGPUTS("File is closed, opening...\n");
+			DEBUGPRINTF("File name: %s\n", file->shared->name);
+			file->shared->file = fopen(file->shared->name, "r+b");
+			if(!file->shared->file)
+				file->shared->file = fopen(file->shared->name,"w+b");
+			if(!file->shared->file)
+			{
+				file->shared->status = FILE_CANT_OPEN;
+				file->shared->size = 0;
+				break;
+			}
+			if(file->shared->status == FILE_NOSIZE)
+			{
+				DEBUGPUTS("Getting file size.\n");
+				fseek(file->shared->file, 0, SEEK_END);
+				file->shared->size = ftell(file->shared->file);
+				DEBUGPRINTF("File size: %d.\n", file->shared->size);
+			}
+				
+			file->shared->status = FILE_WRITE;
+			break;
+		default://file is already open
+			break;
+	}
+	DEBUGPRINTF("Seeking to %d\n", file->offset);
+	if(file->shared->file)
+		fseek(file->shared->file, file->offset, SEEK_SET);
+	DEBUGPUTS("Done.\n");
+}
+
+int vis_file_put_string(datum ** inputlist, queue_entry * worker_entry)
+{
+	file_data * file;
+	int written;
+	inputlist[0] = copy_datum(inputlist[0], 0);
+	file = ((file_data *)inputlist[0]->c.generic.data);
+	VIS_EnterCriticalSection(file->shared->lock);
+		vis_file_write_open_check(file);
+		written = fwrite(inputlist[1]->c.generic.data,1,inputlist[1]->c.generic.len-1,file->shared->file);
+		file->offset += written;
+		if(file->offset > file->shared->size)
+			file->shared->size = file->offset;
+	VIS_LeaveCriticalSection(file->shared->lock);
+	release_ref(inputlist[1]);
+	return 0;
+}
+
+int vis_file_length(datum ** inputlist, queue_entry * worker_entry)
+{
+	file_data * file;
+	int written;
+	int size;
+	file = ((file_data *)inputlist[0]->c.generic.data);
+	VIS_EnterCriticalSection(file->shared->lock);
+		vis_file_read_open_check(file);
+		size = file->shared->size;
+	VIS_LeaveCriticalSection(file->shared->lock);
+	release_ref(inputlist[0]);
+	inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+	inputlist[0]->c.integers.num_a = size;
+	return 0;
+}