#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "../common.h"
#include "param.h"
#define INVALID_FORMAT_ERROR(fn) \
nerv_error(L, "Invalid param file: %s", fn)
#define CHECK_FORMAT(exp, ret, fname) \
do { \
if ((exp) != (ret)) INVALID_FORMAT_ERROR(fn); \
} while (0)
const char *nerv_param_file_tname = "nerv.ParamFile";
const char *nerv_param_file_handle_tname = "nerv.ParamFileHandle";
const char *nerv_param_chunk_info_tname = "nerv.ParamChunkInfo";
const char *nerv_param_chunk_data_tname = "nerv.ParamChunkData";
#define PARAM_HEADER_SIZE 16
enum {
NORMAL,
INVALID_FORMAT,
END_OF_FILE,
SECTION_OVERFLOW,
WRITE_ERROR
};
size_t read_param_header_plain(FILE *fp, int *status) {
static char buff[PARAM_HEADER_SIZE];
int i;
size_t size = 0;
*status = NORMAL;
if (fread(buff, 1, PARAM_HEADER_SIZE, fp) != PARAM_HEADER_SIZE)
{
if (feof(fp)) *status = END_OF_FILE;
else *status = INVALID_FORMAT;
}
for (i = 0; i < PARAM_HEADER_SIZE; i++)
if (isdigit(buff[i]))
size = size * 10 + buff[i] - '0';
fprintf(stderr, "header: %lu\n", size);
return size;
}
#define CHECK_WRITE(status) \
do { \
if (status == SECTION_OVERFLOW) \
nerv_error(L, "section overflowed"); \
else if (status == WRITE_ERROR) \
nerv_error(L, "error while writing"); \
} while (0)
void write_param_header_plain(FILE *fp, size_t size, int *status) {
static char buff[PARAM_HEADER_SIZE];
int i;
*status = NORMAL;
for (i = PARAM_HEADER_SIZE - 3; i > 0; i--, size /= 10)
buff[i] = size % 10 + '0';
if (size)
{
*status = SECTION_OVERFLOW;
return;
}
buff[0] = '[';
buff[PARAM_HEADER_SIZE - 2] = ']';
buff[PARAM_HEADER_SIZE - 1] = '\n';
if (fwrite(buff, 1, PARAM_HEADER_SIZE, fp) != PARAM_HEADER_SIZE)
{
*status = WRITE_ERROR;
return;
}
}
ParamChunkData *get_param_chunk_data(FILE *fp, ParamChunkInfo *info) {
ParamChunkData *pcd = (ParamChunkData *)malloc(sizeof(ParamChunkData));
pcd->data = (char *)malloc(info->length);
pcd->fp = fmemopen(pcd->data, info->length, "r");
assert(fseeko(fp, info->offset, SEEK_SET) == 0);
assert(fread(pcd->data, 1, info->length, fp) == (size_t)info->length);
return pcd;
}
const char *read_param_metadata(lua_State *L, FILE *fp, const char *fn) {
#define LINEBUFF_SIZE 1024
static char buff[7 + LINEBUFF_SIZE] = "return ";
CHECK_FORMAT(fgets(buff + 7, LINEBUFF_SIZE, fp), buff + 7, fn);
fprintf(stderr, "metadata: %s\n", buff);
return buff;
}
void write_param_metadata(FILE *fp, const char *metadata_str, int *status) {
size_t size = strlen(metadata_str);
*status = NORMAL;
if (fwrite(metadata_str, 1, size, fp) != size ||
fprintf(fp, "\n") < 0)
{
*status = WRITE_ERROR;
return;
}
fprintf(stderr, "metadata: %s\n", metadata_str);
}
int nerv_param_file_open_write(lua_State *L, const char *fn) {
FILE *fp = fopen(fn, "w");
ParamFileHandle *lfp;
if (!fp) nerv_error(L, "Error while opening param file: %s", fn);
lfp = (ParamFileHandle *)malloc(sizeof(ParamFileHandle));
lfp->fp = fp;
luaT_pushudata(L, lfp, nerv_param_file_handle_tname);