SBDP02/tape.c
2018-12-14 19:57:49 +01:00

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);
}