comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:76568becd6d6
1 #include "structs.h"
2 #include "datum.h"
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 int vis_file_from_string(datum ** inputlist, queue_entry * worker_entry)
8 {
9 datum * output;
10 file_data * file;
11 output = new_datum(BUILTIN_TYPE_FILE, 1, sizeof(file_data), worker_entry->instance->def->program);
12 file = output->c.generic.data;
13 file->shared = malloc(sizeof(shared_file) + inputlist[0]->c.generic.len-1);
14 strcpy(file->shared->name, inputlist[0]->c.generic.data);
15 DEBUGPRINTF("File from string name: %s\n", file->shared->name);
16 release_ref(inputlist[0]);
17 file->shared->status = FILE_NOSIZE;
18 VIS_InitializeCriticalSection(file->shared->lock);
19 file->shared->ref_count = 1;
20 file->offset = 0;
21 inputlist[0] = output;
22 return 0;
23 }
24
25 void vis_file_read_open_check(file_data * file)
26 {
27 switch(file->shared->status)
28 {
29 case FILE_NOSIZE:
30 case FILE_CLOSED:
31 DEBUGPUTS("File is closed, opening...\n");
32 DEBUGPRINTF("File name: %s\n", file->shared->name);
33 file->shared->file = fopen(file->shared->name, "rb");
34 if(!file->shared->file)
35 {
36 file->shared->status = FILE_CANT_OPEN;
37 file->shared->size = 0;
38 break;
39 }
40 if(file->shared->status == FILE_NOSIZE)
41 {
42 DEBUGPUTS("Getting file size.\n");
43 fseek(file->shared->file, 0, SEEK_END);
44 file->shared->size = ftell(file->shared->file);
45 DEBUGPRINTF("File size: %d.\n", file->shared->size);
46 }
47
48 file->shared->status = FILE_READ;
49 break;
50 default://file is already open
51 break;
52 }
53 DEBUGPRINTF("Seeking to %d\n", file->offset);
54 if(file->shared->file)
55 fseek(file->shared->file, file->offset, SEEK_SET);
56 DEBUGPUTS("Done.\n");
57 }
58
59 int vis_file_get_fstring(datum ** inputlist, queue_entry * worker_entry)
60 {
61 file_data * file;
62 datum * output = new_datum(BUILTIN_TYPE_STRING, 1, inputlist[1]->c.integers.num_a+1, worker_entry->instance->def->program);
63 inputlist[0] = copy_datum(inputlist[0], 0);
64 if(inputlist[1]->c.integers.num_a > 0)
65 {
66 file = (file_data *)inputlist[0]->c.generic.data;
67 VIS_EnterCriticalSection(file->shared->lock);
68 vis_file_read_open_check(file);
69 fread(output->c.generic.data,1,inputlist[1]->c.integers.num_a, file->shared->file);
70 VIS_LeaveCriticalSection(file->shared->lock);
71 file->offset += inputlist[1]->c.integers.num_a;
72 }
73 ((char *)output->c.generic.data)[inputlist[1]->c.integers.num_a] = '\0';
74 release_ref(inputlist[1]);
75 inputlist[1] = output;
76 return 0;
77 }
78 #define FILE_SEARCH_BUFFER_SIZE 512
79
80 typedef struct bufferlist
81 {
82 char buffer[FILE_SEARCH_BUFFER_SIZE];
83 int index;
84 struct bufferlist * next;
85 } bufferlist;
86
87 int vis_file_get_dstring(datum ** inputlist, queue_entry * worker_entry)
88 {
89 BOOL found = FALSE;
90 bufferlist buffers;
91 bufferlist * current, *temp,*temp2;
92 int i,j,k,startk;
93 int found_entry;
94 int string_offset;
95 int search_offset;
96 bufferlist * search_start;
97 int search_start_offset;
98 int *search_offsets;
99 bufferlist ** search_starts;
100 int *search_start_offsets;
101 int read_bytes;
102
103 list_data * list;
104 file_data * file;
105
106 inputlist[0] = copy_datum(inputlist[0], 0);
107 file = (file_data *)inputlist[0]->c.generic.data;
108 buffers.next = NULL;
109 DEBUGPUTS("Entering critical section.\n");
110 VIS_EnterCriticalSection(file->shared->lock);
111 if(file->offset >= file->shared->size)
112 {
113 VIS_LeaveCriticalSection(file->shared->lock);
114 release_ref(inputlist[0]);
115 release_ref(inputlist[1]);
116 inputlist[0] = inputlist[1] = inputlist[2] = NULL;
117 inputlist[3] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
118 datum_set_yesno(inputlist[3], 1);
119 return 0;
120 }
121 if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST)
122 {
123
124 list = ((list_data *)inputlist[1]->c.generic.data);
125 DEBUGPRINTF("Delimeter input is a list with %d entries.\n", list->num_entries);
126 search_offsets = malloc(sizeof(int) * (list->num_entries));
127 DEBUGPRINTF("Allocated %d bytes.\n", sizeof(int) * (list->num_entries));
128 search_starts = malloc(sizeof(bufferlist *) * (list->num_entries));
129 DEBUGPRINTF("Allocated %d bytes.\n", sizeof(bufferlist *) * (list->num_entries));
130 search_start_offsets = malloc(sizeof(int) * (list->num_entries));
131 DEBUGPRINTF("Allocated %d bytes.\n", sizeof(int) * (list->num_entries));
132 for(i = 0; i < list->num_entries; ++i)
133 {
134 DEBUGPRINTF("Setting search_offsets[%d] = 0.\n", i);
135 search_offsets[i] = 0;
136 }
137 }
138 search_offset = 0;
139 current = &buffers;
140 current->index = 0;
141
142 DEBUGPUTS("In critical section.\n");
143 vis_file_read_open_check(file);
144 DEBUGPUTS("File open.");
145 while(!found && !feof(file->shared->file))
146 {
147 DEBUGPRINTF("Reading %d bytes from file\n", FILE_SEARCH_BUFFER_SIZE);
148 read_bytes = fread(current->buffer, 1, FILE_SEARCH_BUFFER_SIZE, file->shared->file);
149 DEBUGPRINTF("fread read %d bytes\n", read_bytes);
150 for(i = 0; i < read_bytes && !found; ++i)
151 {
152 DEBUGPRINTF("Checking character #%d (%c)\n", i, current->buffer[i]);
153 switch(inputlist[1]->company->type_id)
154 {
155 case BUILTIN_TYPE_WHOLE:
156 if((int)current->buffer[i] == inputlist[1]->c.integers.num_a)
157 {
158 found = TRUE;
159 search_offset = 1;
160 search_start = current;
161 search_start_offset = i;
162 }
163 break;
164 case BUILTIN_TYPE_STRING:
165 if(current->buffer[i] == ((char *)inputlist[1]->c.generic.data)[search_offset])
166 {
167 if(search_offset == 0)
168 {
169 search_start = current;
170 search_start_offset = i;
171 }
172 ++search_offset;
173 if(search_offset == (inputlist[1]->c.generic.len-1))
174 found = TRUE;
175 }
176 else
177 {
178 if(search_offset > 0)
179 {
180 current = search_start;
181 i = search_start_offset;
182 }
183 search_offset = 0;
184 }
185 break;
186 case BUILTIN_TYPE_LIST:
187 for(j = 0; j < list->num_entries; ++j)
188 {
189 DEBUGPRINTF("Testing list entry %d against character %d in buffer %d\n", j, i, current->index);
190 if(list->entries[j]->company->type_id == BUILTIN_TYPE_WHOLE && (int)current->buffer[i] == list->entries[j]->c.integers.num_a)
191 {
192 DEBUGPUTS("Matched whole number entry.\n");
193 found = TRUE;
194 found_entry = j;
195 search_offset = 1;
196 search_start = current;
197 search_start_offset = i;
198 break;
199 }
200 else if(list->entries[j]->company->type_id == BUILTIN_TYPE_STRING)
201 {
202 DEBUGPUTS("String entry.\n");
203 if(current->buffer[i] == ((char *)list->entries[j]->c.generic.data)[search_offsets[j]])
204 {
205 DEBUGPRINTF("%c in buffer matches character #%d in entry.\n", current->buffer[i], search_offsets[j]);
206 if(search_offsets[j] == 0)
207 {
208 search_starts[j] = current;
209 search_start_offsets[j] = i;
210 }
211 ++search_offsets[j];
212 if(search_offsets[j] == (list->entries[j]->c.generic.len-1))
213 {
214 DEBUGPUTS("Entire string matched.\n");
215 found = TRUE;
216 found_entry = j;
217 search_offset = search_offsets[j];
218 search_start = search_starts[j];
219 search_start_offset = search_start_offsets[j];
220 break;
221 }
222 }
223 else if(search_offsets[j] > 0)
224 {
225 DEBUGPRINTF("%c in bufer does not match character #%d in entry.\n", current->buffer[i], search_offsets[j]);
226 temp = search_starts[j];
227 search_offsets[j] = 0;
228 startk = search_start_offsets[j];
229 while(temp && !found)
230 {
231 DEBUGPRINTF("Scanning block %d for possible missed match from %d to %d.\n", temp->index, startk, (temp == current ? i : FILE_SEARCH_BUFFER_SIZE)-1);
232 for(k = startk; k < (temp == current ? i : FILE_SEARCH_BUFFER_SIZE); ++k)
233 {
234 if(temp->buffer[k] == ((char *)list->entries[j]->c.generic.data)[search_offsets[j]])
235 {
236 if(!search_offsets[j])
237 {
238 search_starts[j] = temp;
239 search_start_offsets[j] = k;
240 }
241 ++search_offsets[j];
242 if(search_offset == (list->entries[j]->c.generic.len-1))
243 {
244 found = TRUE;
245 found_entry = j;
246 search_start = search_starts[j];
247 search_start_offset = search_start_offsets[j];
248 }
249 }
250 else
251 {
252 if(search_offsets[j] > 0)
253 {
254 temp = search_starts[j];
255 k = search_start_offsets[j];
256 }
257 search_offsets[j] = 0;
258 }
259 }
260 startk = 0;
261 temp = temp->next;
262 }
263
264 }
265 else
266 search_offsets[j] = 0;
267
268 }
269 }
270 break;
271 }
272 }
273 if(!found && !feof(file->shared->file))
274 {
275 current->next = malloc(sizeof(bufferlist));
276 DEBUGPRINTF("Allocated next buffer at %X (%d bytes)\n", current->next, sizeof(bufferlist));
277 current->next->index = current->index+1;
278 current->next->next = NULL;
279 current = current->next;
280 }
281 }
282 VIS_LeaveCriticalSection(file->shared->lock);
283 if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST)
284 {
285 VIS_FREE(search_offsets, "Get DString@File, search offsets");
286 VIS_FREE(search_starts, "Get DString@File, search starts");
287 VIS_FREE(search_start_offsets, "Get DString@File, search start offsets");
288 }
289 if(found)
290 {
291 DEBUGPUTS("Found a delimeter");
292 if(inputlist[1]->company->type_id == BUILTIN_TYPE_LIST)
293 {
294 inputlist[2] = add_ref(list->entries[found_entry]);
295 release_ref(inputlist[1]);
296 }
297 else
298 inputlist[2] = inputlist[1];
299 inputlist[3] = NULL;
300 }
301 else
302 {
303 DEBUGPUTS("Didn't find a delimeter");
304 release_ref(inputlist[1]);
305 inputlist[2] = NULL;
306 inputlist[3] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
307 datum_set_yesno(inputlist[3], 0);
308 }
309 //Does this need to be here still or was it just working around another bug?
310 if(search_start_offset < 0)
311 search_start_offset = 0;
312 if(!found) {
313 search_start = current;
314 search_start_offset = i;
315 }
316 if(found)
317 {
318 inputlist[1] = new_datum(BUILTIN_TYPE_STRING, 1, FILE_SEARCH_BUFFER_SIZE * current->index + search_start_offset+1, worker_entry->instance->def->program);
319 //file->offset += FILE_SEARCH_BUFFER_SIZE * current->index + search_start_offset + search_offset;
320 file->offset += FILE_SEARCH_BUFFER_SIZE * search_start->index + search_start_offset + search_offset;
321 }
322 else
323 {
324 inputlist[1] = new_datum(BUILTIN_TYPE_STRING, 1, FILE_SEARCH_BUFFER_SIZE * current->index + read_bytes+1, worker_entry->instance->def->program);
325 file->offset += FILE_SEARCH_BUFFER_SIZE * current->index + read_bytes;
326 }
327 temp = &buffers;
328 string_offset = 0;
329 while(temp)
330 {
331 DEBUGPRINTF("Copying from index %d to offset %X\n", temp->index, string_offset);
332 if(temp == search_start)
333 {
334 //if(found)
335 //{
336 temp->buffer[search_start_offset] = '\0';
337 memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, search_start_offset);
338 string_offset += search_start_offset;
339 /*}
340 else
341 {
342 memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, i);
343 string_offset += i;
344 }*/
345 break;
346 }
347 else
348 {
349 memcpy(((char *)inputlist[1]->c.generic.data)+string_offset, temp->buffer, FILE_SEARCH_BUFFER_SIZE);
350 string_offset += FILE_SEARCH_BUFFER_SIZE;
351 }
352 if(temp != &buffers)
353 {
354 temp2 = temp->next;
355 VIS_FREE(temp, "Get DString@File, buffer node");
356 temp = temp2;
357 }
358 else
359 temp = temp->next;
360 }
361 while(temp)
362 {
363 if(temp != &buffers)
364 {
365 temp2 = temp->next;
366 DEBUGPRINTF("Freeing %X\n", temp);
367 VIS_FREE(temp, "Get DString@File, buffer node");
368 temp = temp2;
369 }
370 else
371 temp = temp->next;
372 }
373 ((char *)inputlist[1]->c.generic.data)[string_offset] = '\0';
374 DEBUGPRINTF("Output string: %s\n", inputlist[1]->c.generic.data);
375 return 0;
376 }
377
378 int vis_file_get_byte(datum ** inputlist, queue_entry * worker_entry)
379 {
380 file_data * file;
381 BOOL eof;
382 char num;
383
384 inputlist[0] = copy_datum(inputlist[0], 0);
385 file = (file_data *)inputlist[0]->c.generic.data;
386 VIS_EnterCriticalSection(file->shared->lock);
387 if(!(eof = (file->offset >= file->shared->size)))
388 {
389 vis_file_read_open_check(file);
390 fread(&num,sizeof(char),1, file->shared->file);
391 }
392 VIS_LeaveCriticalSection(file->shared->lock);
393 if(eof)
394 {
395 release_ref(inputlist[0]);
396 inputlist[0] = inputlist[1] = NULL;
397 inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
398 datum_set_yesno(inputlist[2], 1);
399 }
400 else
401 {
402 inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
403 inputlist[1]->c.integers.num_a = num;
404 inputlist[2] = NULL;
405 file->offset += sizeof(char);
406 }
407 return 0;
408 }
409
410 int vis_file_get_word(datum ** inputlist, queue_entry * worker_entry)
411 {
412 file_data * file;
413 BOOL eof;
414 short num;
415
416 inputlist[0] = copy_datum(inputlist[0], 0);
417 file = (file_data *)inputlist[0]->c.generic.data;
418 VIS_EnterCriticalSection(file->shared->lock);
419 if(!(eof = (file->offset >= file->shared->size)))
420 {
421 vis_file_read_open_check(file);
422 fread(&num,sizeof(short),1, file->shared->file);
423 }
424 VIS_LeaveCriticalSection(file->shared->lock);
425 if(eof)
426 {
427 release_ref(inputlist[0]);
428 inputlist[0] = inputlist[1] = NULL;
429 inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
430 datum_set_yesno(inputlist[2], 1);
431 }
432 else
433 {
434 inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
435 inputlist[1]->c.integers.num_a = num;
436 inputlist[2] = NULL;
437 file->offset += sizeof(short);
438 }
439 return 0;
440 }
441
442 int vis_file_get_long(datum ** inputlist, queue_entry * worker_entry)
443 {
444 file_data * file;
445 BOOL eof;
446 long num;
447
448 inputlist[0] = copy_datum(inputlist[0], 0);
449 file = (file_data *)inputlist[0]->c.generic.data;
450 VIS_EnterCriticalSection(file->shared->lock);
451 if(!(eof = (file->offset >= file->shared->size)))
452 {
453 vis_file_read_open_check(file);
454 fread(&num,sizeof(long),1, file->shared->file);
455 }
456 VIS_LeaveCriticalSection(file->shared->lock);
457 if(eof)
458 {
459 release_ref(inputlist[0]);
460 inputlist[0] = inputlist[1] = NULL;
461 inputlist[2] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
462 datum_set_yesno(inputlist[2], 1);
463 }
464 else
465 {
466 inputlist[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
467 inputlist[1]->c.integers.num_a = num;
468 inputlist[2] = NULL;
469 file->offset += sizeof(long);
470 }
471 return 0;
472 }
473
474 void vis_file_write_open_check(file_data * file)
475 {
476 switch(file->shared->status)
477 {
478 case FILE_READ:
479 fclose(file->shared->file);
480 case FILE_NOSIZE:
481 case FILE_CLOSED:
482 DEBUGPUTS("File is closed, opening...\n");
483 DEBUGPRINTF("File name: %s\n", file->shared->name);
484 file->shared->file = fopen(file->shared->name, "r+b");
485 if(!file->shared->file)
486 file->shared->file = fopen(file->shared->name,"w+b");
487 if(!file->shared->file)
488 {
489 file->shared->status = FILE_CANT_OPEN;
490 file->shared->size = 0;
491 break;
492 }
493 if(file->shared->status == FILE_NOSIZE)
494 {
495 DEBUGPUTS("Getting file size.\n");
496 fseek(file->shared->file, 0, SEEK_END);
497 file->shared->size = ftell(file->shared->file);
498 DEBUGPRINTF("File size: %d.\n", file->shared->size);
499 }
500
501 file->shared->status = FILE_WRITE;
502 break;
503 default://file is already open
504 break;
505 }
506 DEBUGPRINTF("Seeking to %d\n", file->offset);
507 if(file->shared->file)
508 fseek(file->shared->file, file->offset, SEEK_SET);
509 DEBUGPUTS("Done.\n");
510 }
511
512 int vis_file_put_string(datum ** inputlist, queue_entry * worker_entry)
513 {
514 file_data * file;
515 int written;
516 inputlist[0] = copy_datum(inputlist[0], 0);
517 file = ((file_data *)inputlist[0]->c.generic.data);
518 VIS_EnterCriticalSection(file->shared->lock);
519 vis_file_write_open_check(file);
520 written = fwrite(inputlist[1]->c.generic.data,1,inputlist[1]->c.generic.len-1,file->shared->file);
521 file->offset += written;
522 if(file->offset > file->shared->size)
523 file->shared->size = file->offset;
524 VIS_LeaveCriticalSection(file->shared->lock);
525 release_ref(inputlist[1]);
526 return 0;
527 }
528
529 int vis_file_length(datum ** inputlist, queue_entry * worker_entry)
530 {
531 file_data * file;
532 int written;
533 int size;
534 file = ((file_data *)inputlist[0]->c.generic.data);
535 VIS_EnterCriticalSection(file->shared->lock);
536 vis_file_read_open_check(file);
537 size = file->shared->size;
538 VIS_LeaveCriticalSection(file->shared->lock);
539 release_ref(inputlist[0]);
540 inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
541 inputlist[0]->c.integers.num_a = size;
542 return 0;
543 }