97 lines
2.3 KiB
C
97 lines
2.3 KiB
C
#include "tape.h"
|
|
#include "common.h"
|
|
#include <stdlib.h>
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
|
|
tape_t* tape_open(const char* filename, const char* mode)
|
|
{
|
|
file_t *file = file_open(filename, mode);
|
|
printfv(VERBOSITY_VERBOSE, "Opening file %s in mode %s.\n", filename, mode);
|
|
|
|
if (!file) {
|
|
fprintf(stderr, "Cannot open %s in %s mode.", filename, mode);
|
|
return NULL;
|
|
}
|
|
|
|
tape_t* tape = malloc(sizeof(tape_t));
|
|
|
|
fseek(file->file, 0, SEEK_END);
|
|
|
|
tape->file = file;
|
|
tape->end = ftell(file->file);
|
|
|
|
return tape;
|
|
}
|
|
|
|
void tape_close(tape_t* tape)
|
|
{
|
|
file_close(tape->file);
|
|
}
|
|
|
|
void* tape_read(tape_t* tape, offset_t offset, void* record, size_t size)
|
|
{
|
|
char buffer[PAGE_SIZE];
|
|
|
|
page_t page = offset / PAGE_SIZE;
|
|
offset = offset % PAGE_SIZE;
|
|
|
|
offset_t written = 0;
|
|
file_read(tape->file, page, buffer, PAGE_SIZE);
|
|
|
|
while (size > PAGE_SIZE - offset) {
|
|
memcpy(record + written, buffer + offset, PAGE_SIZE - offset);
|
|
|
|
size -= PAGE_SIZE - offset;
|
|
written += PAGE_SIZE - offset;
|
|
|
|
page++;
|
|
offset = 0;
|
|
|
|
file_read(tape->file, page, buffer, PAGE_SIZE);
|
|
}
|
|
|
|
memcpy(record + written, buffer + offset, size);
|
|
|
|
return record;
|
|
}
|
|
|
|
offset_t tape_write(tape_t* tape, offset_t location, void* record, size_t size)
|
|
{
|
|
char buffer[PAGE_SIZE];
|
|
|
|
page_t page = location / PAGE_SIZE;
|
|
offset_t offset = location % PAGE_SIZE;
|
|
|
|
offset_t written = 0;
|
|
size_t original = file_read(tape->file, page, buffer, PAGE_SIZE);
|
|
while (size > PAGE_SIZE - offset) {
|
|
memcpy(buffer + offset, record + written, PAGE_SIZE - offset);
|
|
|
|
size -= PAGE_SIZE - offset;
|
|
written += PAGE_SIZE - offset;
|
|
|
|
file_write(tape->file, page, buffer, PAGE_SIZE);
|
|
|
|
page++;
|
|
offset = 0;
|
|
|
|
file_read(tape->file, page, buffer, PAGE_SIZE);
|
|
}
|
|
|
|
memcpy(buffer + offset, record + written, size);
|
|
file_write(tape->file, page, buffer, offset + size > original ? offset + size : original);
|
|
|
|
written += size;
|
|
if (location + written > tape->end) {
|
|
tape->end = location + written;
|
|
}
|
|
|
|
return location;
|
|
}
|
|
|
|
offset_t tape_append(tape_t* tape, void* record, size_t size)
|
|
{
|
|
return tape_write(tape, tape->end, record, size);
|
|
}
|