Mercurial > repos > rhope
view file.c @ 57:2174878a6e4b
Avoid unnecessary nested switch
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 08 Oct 2009 02:12:25 -0400 |
parents | 20d40cb8abf3 |
children |
line wrap: on
line source
#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; } int vis_file_get_double(datum ** inputlist, queue_entry * worker_entry) { file_data * file; BOOL eof; double 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(num),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_REAL, 3, 0, worker_entry->instance->def->program); inputlist[1]->c.real = num; inputlist[2] = NULL; file->offset += sizeof(num); } 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; } int vis_file_truncate(datum ** inputlist, queue_entry * worker_entry) { file_data * file; inputlist[0] = copy_datum(inputlist[0], 0); file = inputlist[0]->c.generic.data; VIS_EnterCriticalSection(file->shared->lock); switch(file->shared->status) { case FILE_READ: case FILE_WRITE: fclose(file->shared->file); default: break; } file->shared->file = fopen(file->shared->name,"wb"); file->shared->size = 0; file->shared->status = FILE_WRITE; VIS_LeaveCriticalSection(file->shared->lock); file->offset = 0; return 0; }