extract gamedata into a separate file.

This commit is contained in:
Enno Rehling 2016-02-12 22:06:31 +01:00
parent 0197ad16cc
commit 6ca81646eb
7 changed files with 140 additions and 74 deletions

View File

@ -35,7 +35,7 @@ static int tolua_storage_create(lua_State * L)
const char *type = tolua_tostring(L, 2, "rb"); const char *type = tolua_tostring(L, 2, "rb");
gamedata *data; gamedata *data;
data = gamedata_open(filename, type); data = gamedata_open(filename, type, RELEASE_VERSION);
if (data) { if (data) {
tolua_pushusertype(L, (void *)data, TOLUA_CAST "storage"); tolua_pushusertype(L, (void *)data, TOLUA_CAST "storage");
return 1; return 1;

View File

@ -60,6 +60,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/event.h> #include <util/event.h>
#include <util/filereader.h> #include <util/filereader.h>
#include <util/goodies.h> #include <util/goodies.h>
#include <util/gamedata.h>
#include <util/language.h> #include <util/language.h>
#include <util/lists.h> #include <util/lists.h>
#include <util/log.h> #include <util/log.h>
@ -1954,51 +1955,6 @@ int writegame(const char *filename)
return 0; return 0;
} }
void gamedata_close(gamedata *data) {
binstore_done(data->store);
fstream_done(&data->strm);
}
gamedata *gamedata_open(const char *filename, const char *mode) {
FILE *F = fopen(filename, mode);
if (F) {
gamedata *data = (gamedata *)calloc(1, sizeof(gamedata));
storage *store = (storage *)calloc(1, sizeof(storage));
int err = 0;
size_t sz;
data->store = store;
if (strchr(mode, 'r')) {
sz = fread(&data->version, 1, sizeof(int), F);
if (sz != sizeof(int)) {
err = ferror(F);
}
else {
err = fseek(F, sizeof(int), SEEK_CUR);
}
}
else if (strchr(mode, 'w')) {
int n = STREAM_VERSION;
data->version = RELEASE_VERSION;
fwrite(&data->version, sizeof(int), 1, F);
fwrite(&n, sizeof(int), 1, F);
}
if (err) {
fclose(F);
free(data);
free(store);
}
else {
fstream_init(&data->strm, F);
binstore_init(store, &data->strm);
return data;
}
}
log_error("could not open %s: %s", filename, strerror(errno));
return 0;
}
int a_readint(attrib * a, void *owner, struct storage *store) int a_readint(attrib * a, void *owner, struct storage *store)
{ {
/* assert(sizeof(int)==sizeof(a->data)); */ /* assert(sizeof(int)==sizeof(a->data)); */

View File

@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define H_KRNL_SAVE #define H_KRNL_SAVE
#include <stream.h> #include <stream.h>
#include <util/gamedata.h> // FIXME: eliminate include dependency from this file
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -31,13 +32,6 @@ extern "C" {
struct spellbook; struct spellbook;
struct unit; struct unit;
typedef struct gamedata {
struct storage *store;
stream strm;
int version;
int encoding;
} gamedata;
#define MAX_INPUT_SIZE DISPLAYSIZE*2 #define MAX_INPUT_SIZE DISPLAYSIZE*2
/* Nach MAX_INPUT_SIZE brechen wir das Einlesen der Zeile ab und nehmen an, /* Nach MAX_INPUT_SIZE brechen wir das Einlesen der Zeile ab und nehmen an,
* dass hier ein Fehler (fehlende ") vorliegt */ * dass hier ein Fehler (fehlende ") vorliegt */
@ -83,9 +77,6 @@ extern "C" {
void create_backup(char *file); void create_backup(char *file);
struct gamedata *gamedata_open(const char *filename, const char *mode);
void gamedata_close(struct gamedata *data);
/* test-only functions that give access to internal implementation details (BAD) */ /* test-only functions that give access to internal implementation details (BAD) */
void _test_write_password(struct gamedata *data, const struct faction *f); void _test_write_password(struct gamedata *data, const struct faction *f);
void _test_read_password(struct gamedata *data, struct faction *f); void _test_read_password(struct gamedata *data, struct faction *f);

View File

@ -1,6 +1,7 @@
#include <platform.h> #include <platform.h>
#include <kernel/config.h> #include <kernel/config.h>
#include <util/attrib.h> #include <util/attrib.h>
#include <util/gamedata.h>
#include <attributes/key.h> #include <attributes/key.h>
#include "save.h" #include "save.h"
@ -43,7 +44,7 @@ static void test_readwrite_unit(CuTest * tc)
{ {
const char *filename = "test.dat"; const char *filename = "test.dat";
char path[MAX_PATH]; char path[MAX_PATH];
gamedata *data; gamedata data;
struct unit *u; struct unit *u;
struct region *r; struct region *r;
struct faction *f; struct faction *f;
@ -58,20 +59,16 @@ static void test_readwrite_unit(CuTest * tc)
u = test_create_unit(f, r); u = test_create_unit(f, r);
join_path(datapath(), filename, path, sizeof(path)); join_path(datapath(), filename, path, sizeof(path));
data = gamedata_open(path, "wb"); CuAssertIntEquals(tc, 0, gamedata_openfile(&data, path, "wb", RELEASE_VERSION)); // TODO: intermittent test (even after the 'b' fix!)
CuAssertPtrNotNull(tc, data); // TODO: intermittent test (even after the 'b' fix!) write_unit(&data, u);
gamedata_close(&data);
write_unit(data, u);
gamedata_close(data);
free_gamedata(); free_gamedata();
f = test_create_faction(0); f = test_create_faction(0);
renumber_faction(f, fno); renumber_faction(f, fno);
data = gamedata_open(path, "rb"); CuAssertIntEquals(tc, 0, gamedata_openfile(&data, path, "rb", RELEASE_VERSION)); // TODO: intermittent test (even after the 'b' fix!)
CuAssertPtrNotNull(tc, data); u = read_unit(&data);
gamedata_close(&data);
u = read_unit(data);
gamedata_close(data);
CuAssertPtrNotNull(tc, u); CuAssertPtrNotNull(tc, u);
CuAssertPtrEquals(tc, f, u->faction); CuAssertPtrEquals(tc, f, u->faction);
@ -86,7 +83,7 @@ static void test_readwrite_attrib(CuTest *tc) {
const char *path = "attrib.dat"; const char *path = "attrib.dat";
test_cleanup(); test_cleanup();
global.data_version = RELEASE_VERSION; // FIXME: hack! global.data_version = RELEASE_VERSION; // FIXME: hack!
data = gamedata_open(path, "wb"); data = gamedata_open(path, "wb", RELEASE_VERSION);
CuAssertPtrNotNull(tc, data); CuAssertPtrNotNull(tc, data);
key_set(&a, 41); key_set(&a, 41);
key_set(&a, 42); key_set(&a, 42);
@ -95,7 +92,7 @@ static void test_readwrite_attrib(CuTest *tc) {
a_removeall(&a, NULL); a_removeall(&a, NULL);
CuAssertPtrEquals(tc, 0, a); CuAssertPtrEquals(tc, 0, a);
data = gamedata_open(path, "rb"); data = gamedata_open(path, "rb", RELEASE_VERSION);
CuAssertPtrNotNull(tc, data); CuAssertPtrNotNull(tc, data);
read_attribs(data->store, &a, NULL); read_attribs(data->store, &a, NULL);
gamedata_close(data); gamedata_close(data);
@ -237,11 +234,11 @@ static void test_read_password(CuTest *tc) {
faction *f; faction *f;
f = test_create_faction(0); f = test_create_faction(0);
faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT)); faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT));
data = gamedata_open(path, "wb"); data = gamedata_open(path, "wb", RELEASE_VERSION);
CuAssertPtrNotNull(tc, data); CuAssertPtrNotNull(tc, data);
_test_write_password(data, f); _test_write_password(data, f);
gamedata_close(data); gamedata_close(data);
data = gamedata_open(path, "rb"); data = gamedata_open(path, "rb", RELEASE_VERSION);
CuAssertPtrNotNull(tc, data); CuAssertPtrNotNull(tc, data);
_test_read_password(data, f); _test_read_password(data, f);
gamedata_close(data); gamedata_close(data);
@ -259,12 +256,12 @@ static void test_read_password_external(CuTest *tc) {
f = test_create_faction(0); f = test_create_faction(0);
faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT)); faction_setpassword(f, password_encode("secret", PASSWORD_DEFAULT));
CuAssertPtrNotNull(tc, f->_password); CuAssertPtrNotNull(tc, f->_password);
data = gamedata_open(path, "wb"); data = gamedata_open(path, "wb", RELEASE_VERSION);
CuAssertPtrNotNull(tc, data); CuAssertPtrNotNull(tc, data);
WRITE_TOK(data->store, (const char *)f->_password); WRITE_TOK(data->store, (const char *)f->_password);
WRITE_TOK(data->store, (const char *)f->_password); WRITE_TOK(data->store, (const char *)f->_password);
gamedata_close(data); gamedata_close(data);
data = gamedata_open(path, "rb"); data = gamedata_open(path, "rb", RELEASE_VERSION);
CuAssertPtrNotNull(tc, data); CuAssertPtrNotNull(tc, data);
data->version = BADCRYPT_VERSION; data->version = BADCRYPT_VERSION;
_test_read_password(data, f); _test_read_password(data, f);

View File

@ -23,6 +23,7 @@ event.c
filereader.c filereader.c
functions.c functions.c
goodies.c goodies.c
gamedata.c
language.c language.c
lists.c lists.c
log.c log.c

98
src/util/gamedata.c Normal file
View File

@ -0,0 +1,98 @@
#include <platform.h>
#include "gamedata.h"
#include "log.h"
#include <storage.h>
#include <filestream.h>
#include <memstream.h>
#include <binarystore.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void gamedata_close(gamedata *data) {
binstore_done(data->store);
fstream_done(&data->strm);
}
void gamedata_init(gamedata *data, storage *store, int version) {
data->version = version;
data->store = store;
binstore_init(data->store, &data->strm);
}
int gamedata_openfile(gamedata *data, const char *filename, const char *mode, int version) {
FILE *F = fopen(filename, mode);
if (F) {
int err = 0;
if (strchr(mode, 'r')) {
size_t sz;
sz = fread(&version, 1, sizeof(int), F);
if (sz != sizeof(int)) {
err = ferror(F);
}
else {
err = fseek(F, sizeof(int), SEEK_CUR);
}
}
else if (strchr(mode, 'w')) {
int n = STREAM_VERSION;
fwrite(&version, sizeof(int), 1, F);
fwrite(&n, sizeof(int), 1, F);
}
if (err) {
fclose(F);
free(data);
}
else {
storage *store = malloc(sizeof(storage));
fstream_init(&data->strm, F);
gamedata_init(data, store, version);
}
return err;
}
return errno;
}
gamedata *gamedata_open(const char *filename, const char *mode, int version) {
FILE *F = fopen(filename, mode);
if (F) {
gamedata *data = (gamedata *)calloc(1, sizeof(gamedata));
storage *store = (storage *)calloc(1, sizeof(storage));
int err = 0;
size_t sz;
data->store = store;
if (strchr(mode, 'r')) {
sz = fread(&data->version, 1, sizeof(int), F);
if (sz != sizeof(int)) {
err = ferror(F);
}
else {
err = fseek(F, sizeof(int), SEEK_CUR);
}
}
else if (strchr(mode, 'w')) {
int n = STREAM_VERSION;
data->version = version;
fwrite(&data->version, sizeof(int), 1, F);
fwrite(&n, sizeof(int), 1, F);
}
if (err) {
fclose(F);
free(data);
free(store);
}
else {
fstream_init(&data->strm, F);
binstore_init(store, &data->strm);
return data;
}
}
log_error("could not open %s: %s", filename, strerror(errno));
return 0;
}

23
src/util/gamedata.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#ifndef _GAMEDATA_H
#define _GAMEDATA_H
#include <stream.h>
struct storage;
typedef struct gamedata {
struct storage *store;
stream strm;
int version;
int encoding;
} gamedata;
void gamedata_close(struct gamedata *data);
struct gamedata *gamedata_open(const char *filename, const char *mode, int version);
int gamedata_openfile(gamedata *data, const char *filename, const char *mode, int version);
#define STREAM_VERSION 2 /* internal encoding of binary files */
#endif