#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nfs_data.h"
int nfs_data_IOMODE = 1;
static int cache_create(nfs_data_Data* data) {
int size = nfs_data_DEF_CACHE_SIZE;
if (data == NULL)
return -1;
if ((size % nfs_data_BLOCK_SIZE) != 0)
size += (nfs_data_BLOCK_SIZE - (size % nfs_data_BLOCK_SIZE));
data->cache = (nfs_data_Cache*)malloc(sizeof(nfs_data_Cache));
if (data->cache == NULL)
return -1;
data->cache->buffer = (char*)malloc(size);
if (data->cache->buffer == NULL)
return -1;
data->cache->size = size;
data->cache->sync = nfs_data_SYNC;
data->cache->position = 0;
fseek(data->file, data->cache->position, 0);
fread(data->cache->buffer, 1, data->cache->size, data->file);
return 0;
}
static int cache_resize(nfs_data_Data* data, int size) {
if (data == NULL)
return -1;
if (data->cache->sync != nfs_data_SYNC)
return -1;
if ((size % nfs_data_BLOCK_SIZE) != 0)
size += (nfs_data_BLOCK_SIZE - (size % nfs_data_BLOCK_SIZE));
if (size <= 0)
size = nfs_data_BLOCK_SIZE;
data->cache->buffer = (char*)realloc(data->cache->buffer, size);
if (data->cache->buffer == NULL)
return -1;
data->cache->size = size;
data->cache->sync = nfs_data_SYNC;
fseek(data->file, data->cache->position, 0);
fread(data->cache->buffer, 1, data->cache->size, data->file);
return 0;
}
static int cache_flush(nfs_data_Data* data) {
if (data->cache == NULL)
return -1;
if (data->cache->sync == nfs_data_SYNC)
return 0;
fseek(data->file, data->cache->position, 0);
fwrite(data->cache->buffer, 1, data->cache->size, data->file);
data->cache->sync = nfs_data_SYNC;
return 0;
}
static int cache_destroy(nfs_data_Data* data) {
cache_flush(data);
if (data->cache->buffer != NULL)
free(data->cache->buffer);
if (data->cache != NULL)
free(data->cache);
data->cache = NULL;
return 0;
}
static int cache_slide(nfs_data_Data* data, int new_position) {
if (data->cache->sync != nfs_data_SYNC)
cache_flush(data);
if ((new_position % nfs_data_BLOCK_SIZE) != 0)
new_position = (int)(new_position / nfs_data_BLOCK_SIZE) * nfs_data_BLOCK_SIZE;
data->cache->position = new_position;
fseek(data->file, data->cache->position, 0);
fread(data->cache->buffer, 1, data->cache->size, data->file);
return 0;
}
static int is_in_cache(nfs_data_Data* data, int block) {
if ((data == NULL) || (data->cache == NULL))
return 0;
if ((block >= (data->cache->position / nfs_data_BLOCK_SIZE)) &&
(block < ((data->cache->position + data->cache->size) / nfs_data_BLOCK_SIZE)))
return 1;
return 0;
}
static int cache_get(nfs_data_Data* data, int abspos, int how_much, void* to) {
int i;
for (i = 0; i < how_much; i += nfs_data_BLOCK_SIZE) {
if (!is_in_cache(data, ((abspos + i) / nfs_data_BLOCK_SIZE)))
cache_slide(data, (int)((abspos + i) / nfs_data_BLOCK_SIZE) * nfs_data_BLOCK_SIZE);
memcpy((char*)to + i,
(void*)((char*)data->cache->buffer + (abspos - data->cache->position + i)),
nfs_data_BLOCK_SIZE);
}
return 0;
}
static int cache_put(nfs_data_Data* data, int abspos, int how_much, void* from) {
int i;
for (i = 0; i < how_much; i += nfs_data_BLOCK_SIZE) {
if (!is_in_cache(data, ((abspos + i) / nfs_data_BLOCK_SIZE)))
cache_slide(data, (int)((abspos + i) / nfs_data_BLOCK_SIZE) * nfs_data_BLOCK_SIZE);
memcpy((void*)((char*)data->cache->buffer + (abspos - data->cache->position + i)),
(char*)from + i,
nfs_data_BLOCK_SIZE);
data->cache->sync = nfs_data_NOT_SYNC;
}
return 0;
}
nfs_data_Data* nfs_data_create(char* filename) {
nfs_data_Data* data;
data = (nfs_data_Data*)malloc(sizeof(nfs_data_Data));
if (data == NULL)
return NULL;
data->filename = (char*)malloc(strlen(filename) + 8);
if (!data->filename)
return NULL;
strcpy(data->filename, filename);
data->file = fopen(filename, "w+b");
if (data->file == NULL)
return NULL;
if (cache_create(data) < 0)
return NULL;
return data;
}
nfs_data_Data* nfs_data_open(char* filename) {
nfs_data_Data* data;
data = (nfs_data_Data*)malloc(sizeof(nfs_data_Data));
if (data == NULL)
return NULL;
data->filename = (char*)malloc(strlen(filename) + 8);
if (!data->filename)
return NULL;
strcpy(data->filename, filename);
if (nfs_data_IOMODE & 2)
data->file = fopen(filename, "r+b");
else
data->file = fopen(filename, "rb");
if (data->file == NULL)
return NULL;
if (cache_create(data) < 0)
return NULL;
return data;
}
void nfs_data_destroy(nfs_data_Data* data) {
char* tempfn = (char*)malloc(strlen(data->filename) + 8);
if (tempfn)
strcpy(tempfn, data->filename);
nfs_data_close(data);
#ifdef WIN32
if (tempfn)
remove(tempfn);
#else
if (tempfn)
unlink(tempfn);
#endif
if (tempfn)
free(tempfn);
}
void nfs_data_close(nfs_data_Data* data) {
cache_destroy(data);
fflush(data->file);
fclose(data->file);
if (data != NULL)
free(data);
}
int nfs_data_set_cache_size(nfs_data_Data* data, int cache_size) {
nfs_data_flush_cache(data);
return cache_resize(data, cache_size);
}
int nfs_data_flush_cache(nfs_data_Data* data) {
if (data->cache->sync != nfs_data_SYNC)
cache_flush(data);
return 0;
}
int nfs_data_write(nfs_data_Data* data, int block_no, void* from) {
if (block_no < 0)
return -1;
return cache_put(data, block_no * nfs_data_BLOCK_SIZE, nfs_data_BLOCK_SIZE, from);
}
int nfs_data_read(nfs_data_Data* data, int block_no, void* to) {
if (block_no < 0)
return -1;
return cache_get(data, block_no * nfs_data_BLOCK_SIZE, nfs_data_BLOCK_SIZE, to);
}
int nfs_data_write_contiguous(nfs_data_Data* data, int block_start, int n, void* from) {
if (block_start < 0)
return -1;
return cache_put(data, block_start * nfs_data_BLOCK_SIZE, n * nfs_data_BLOCK_SIZE, from);
}
int nfs_data_read_contiguous(nfs_data_Data* data, int block_start, int n, void* to) {
if (block_start < 0)
return -1;
return cache_get(data, block_start * nfs_data_BLOCK_SIZE, n * nfs_data_BLOCK_SIZE, to);
}