forked from github/server
optimized storage of attribs.
save the hash instead of the name and save a few bytes.
This commit is contained in:
parent
f630278339
commit
abc3caa6d1
8 changed files with 140 additions and 75 deletions
|
@ -659,7 +659,7 @@ int read_borders(struct storage *store)
|
||||||
type->read(b, store);
|
type->read(b, store);
|
||||||
if (global.data_version < NOBORDERATTRIBS_VERSION) {
|
if (global.data_version < NOBORDERATTRIBS_VERSION) {
|
||||||
attrib *a = NULL;
|
attrib *a = NULL;
|
||||||
int result = a_read(store, &a, b);
|
int result = read_attribs(store, &a, b);
|
||||||
if (border_convert_cb) {
|
if (border_convert_cb) {
|
||||||
border_convert_cb(b, a);
|
border_convert_cb(b, a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,7 @@ void write_groups(struct storage *store, const faction * f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WRITE_INT(store, 0);
|
WRITE_INT(store, 0);
|
||||||
a_write(store, g->attribs, g);
|
write_attribs(store, g->attribs, g);
|
||||||
WRITE_SECTION(store);
|
WRITE_SECTION(store);
|
||||||
}
|
}
|
||||||
WRITE_INT(store, 0);
|
WRITE_INT(store, 0);
|
||||||
|
@ -241,6 +241,6 @@ void read_groups(struct storage *store, faction * f)
|
||||||
if (!a->faction)
|
if (!a->faction)
|
||||||
ur_add(fid, &a->faction, resolve_faction);
|
ur_add(fid, &a->faction, resolve_faction);
|
||||||
}
|
}
|
||||||
a_read(store, &g->attribs, g);
|
read_attribs(store, &g->attribs, g);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -577,6 +577,23 @@ const struct locale *lang)
|
||||||
WRITE_STR(data->store, obuf);
|
WRITE_STR(data->store, obuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int read_attribs(storage *store, attrib **alist, void *owner) {
|
||||||
|
#if RELEASE_VERSION < ATHASH_VERSION
|
||||||
|
return a_read_orig(store, alist, owner);
|
||||||
|
#else
|
||||||
|
return a_read(store, alist, owner);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_attribs(storage *store, attrib *alist, const void *owner)
|
||||||
|
{
|
||||||
|
#if RELEASE_VERSION < ATHASH_VERSION
|
||||||
|
a_write_orig(store, alist, owner);
|
||||||
|
#else
|
||||||
|
a_write(store, alist, owner);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
unit *read_unit(struct gamedata *data)
|
unit *read_unit(struct gamedata *data)
|
||||||
{
|
{
|
||||||
unit *u;
|
unit *u;
|
||||||
|
@ -748,8 +765,7 @@ unit *read_unit(struct gamedata *data)
|
||||||
log_error("Einheit %s hat %u Personen, und %u Trefferpunkte\n", itoa36(u->no), u->number, u->hp);
|
log_error("Einheit %s hat %u Personen, und %u Trefferpunkte\n", itoa36(u->no), u->number, u->hp);
|
||||||
u->hp = u->number;
|
u->hp = u->number;
|
||||||
}
|
}
|
||||||
|
read_attribs(data->store, &u->attribs, u);
|
||||||
a_read(data->store, &u->attribs, u);
|
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,7 +839,7 @@ void write_unit(struct gamedata *data, const unit * u)
|
||||||
}
|
}
|
||||||
WRITE_INT(data->store, u->hp);
|
WRITE_INT(data->store, u->hp);
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
a_write(data->store, u->attribs, u);
|
write_attribs(data->store, u->attribs, u);
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,7 +998,7 @@ static region *readregion(struct gamedata *data, int x, int y)
|
||||||
read_owner(data, &r->land->ownership);
|
read_owner(data, &r->land->ownership);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a_read(data->store, &r->attribs, r);
|
read_attribs(data->store, &r->attribs, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,7 +1062,7 @@ void writeregion(struct gamedata *data, const region * r)
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
a_write(data->store, r->attribs, r);
|
write_attribs(data->store, r->attribs, r);
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,7 +1269,7 @@ faction *readfaction(struct gamedata * data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a_read(data->store, &f->attribs, f);
|
read_attribs(data->store, &f->attribs, f);
|
||||||
read_items(data->store, &f->items);
|
read_items(data->store, &f->items);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
READ_TOK(data->store, name, sizeof(name));
|
READ_TOK(data->store, name, sizeof(name));
|
||||||
|
@ -1338,7 +1354,7 @@ void writefaction(struct gamedata *data, const faction * f)
|
||||||
WRITE_INT(data->store, f->magiegebiet);
|
WRITE_INT(data->store, f->magiegebiet);
|
||||||
|
|
||||||
WRITE_INT(data->store, f->flags & FFL_SAVEMASK);
|
WRITE_INT(data->store, f->flags & FFL_SAVEMASK);
|
||||||
a_write(data->store, f->attribs, f);
|
write_attribs(data->store, f->attribs, f);
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
write_items(data->store, f->items);
|
write_items(data->store, f->items);
|
||||||
WRITE_SECTION(data->store);
|
WRITE_SECTION(data->store);
|
||||||
|
@ -1451,7 +1467,7 @@ int readgame(const char *filename, bool backup)
|
||||||
else {
|
else {
|
||||||
READ_STR(&store, NULL, 0);
|
READ_STR(&store, NULL, 0);
|
||||||
}
|
}
|
||||||
a_read(&store, &global.attribs, NULL);
|
read_attribs(&store, &global.attribs, NULL);
|
||||||
READ_INT(&store, &turn);
|
READ_INT(&store, &turn);
|
||||||
global.data_turn = turn;
|
global.data_turn = turn;
|
||||||
log_debug(" - reading turn %d\n", turn);
|
log_debug(" - reading turn %d\n", turn);
|
||||||
|
@ -1512,7 +1528,7 @@ int readgame(const char *filename, bool backup)
|
||||||
fno = read_faction_reference(&store);
|
fno = read_faction_reference(&store);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a_read(&store, &pl->attribs, pl);
|
read_attribs(&store, &pl->attribs, pl);
|
||||||
if (pl->id != 1094969858) { // Regatta
|
if (pl->id != 1094969858) { // Regatta
|
||||||
addlist(&planes, pl);
|
addlist(&planes, pl);
|
||||||
}
|
}
|
||||||
|
@ -1580,7 +1596,7 @@ int readgame(const char *filename, bool backup)
|
||||||
READ_STR(&store, name, sizeof(name));
|
READ_STR(&store, name, sizeof(name));
|
||||||
b->type = bt_find(name);
|
b->type = bt_find(name);
|
||||||
b->region = r;
|
b->region = r;
|
||||||
a_read(&store, &b->attribs, b);
|
read_attribs(&store, &b->attribs, b);
|
||||||
if (b->type == bt_lighthouse) {
|
if (b->type == bt_lighthouse) {
|
||||||
r->flags |= RF_LIGHTHOUSE;
|
r->flags |= RF_LIGHTHOUSE;
|
||||||
}
|
}
|
||||||
|
@ -1627,7 +1643,7 @@ int readgame(const char *filename, bool backup)
|
||||||
if (sh->type->flags & SFL_NOCOAST) {
|
if (sh->type->flags & SFL_NOCOAST) {
|
||||||
sh->coast = NODIRECTION;
|
sh->coast = NODIRECTION;
|
||||||
}
|
}
|
||||||
a_read(&store, &sh->attribs, sh);
|
read_attribs(&store, &sh->attribs, sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
*shp = 0;
|
*shp = 0;
|
||||||
|
@ -1777,7 +1793,7 @@ int writegame(const char *filename)
|
||||||
WRITE_INT(&store, game_id());
|
WRITE_INT(&store, game_id());
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
|
|
||||||
a_write(&store, global.attribs, NULL);
|
write_attribs(&store, global.attribs, NULL);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
|
|
||||||
WRITE_INT(&store, turn);
|
WRITE_INT(&store, turn);
|
||||||
|
@ -1807,7 +1823,7 @@ int writegame(const char *filename)
|
||||||
w = w->next;
|
w = w->next;
|
||||||
}
|
}
|
||||||
write_faction_reference(NULL, &store); /* mark the end of the list */
|
write_faction_reference(NULL, &store); /* mark the end of the list */
|
||||||
a_write(&store, pl->attribs, pl);
|
write_attribs(&store, pl->attribs, pl);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1852,7 +1868,7 @@ int writegame(const char *filename)
|
||||||
WRITE_INT(&store, b->size);
|
WRITE_INT(&store, b->size);
|
||||||
WRITE_TOK(&store, b->type->_name);
|
WRITE_TOK(&store, b->type->_name);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
a_write(&store, b->attribs, b);
|
write_attribs(&store, b->attribs, b);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1870,7 +1886,7 @@ int writegame(const char *filename)
|
||||||
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
|
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
|
||||||
WRITE_INT(&store, sh->coast);
|
WRITE_INT(&store, sh->coast);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
a_write(&store, sh->attribs, sh);
|
write_attribs(&store, sh->attribs, sh);
|
||||||
WRITE_SECTION(&store);
|
WRITE_SECTION(&store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,9 @@ extern "C" {
|
||||||
void read_spellbook(struct spellbook **bookp, struct storage *store, int(*get_level)(const struct spell * sp, void *), void * cbdata);
|
void read_spellbook(struct spellbook **bookp, struct storage *store, int(*get_level)(const struct spell * sp, void *), void * cbdata);
|
||||||
void write_spellbook(const struct spellbook *book, struct storage *store);
|
void write_spellbook(const struct spellbook *book, struct storage *store);
|
||||||
|
|
||||||
|
void write_attribs(struct storage *store, struct attrib *alist, const void *owner);
|
||||||
|
int read_attribs(struct storage *store, struct attrib **alist, void *owner);
|
||||||
|
|
||||||
void write_unit(struct gamedata *data, const struct unit *u);
|
void write_unit(struct gamedata *data, const struct unit *u);
|
||||||
struct unit *read_unit(struct gamedata *data);
|
struct unit *read_unit(struct gamedata *data);
|
||||||
|
|
||||||
|
|
|
@ -72,14 +72,14 @@ static void test_readwrite_attrib(CuTest *tc) {
|
||||||
CuAssertPtrNotNull(tc, data);
|
CuAssertPtrNotNull(tc, data);
|
||||||
add_key(&a, 41);
|
add_key(&a, 41);
|
||||||
add_key(&a, 42);
|
add_key(&a, 42);
|
||||||
a_write(data->store, a, NULL);
|
write_attribs(data->store, a, NULL);
|
||||||
gamedata_close(data);
|
gamedata_close(data);
|
||||||
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");
|
||||||
CuAssertPtrNotNull(tc, data);
|
CuAssertPtrNotNull(tc, data);
|
||||||
a_read(data->store, &a, NULL);
|
read_attribs(data->store, &a, NULL);
|
||||||
gamedata_close(data);
|
gamedata_close(data);
|
||||||
CuAssertPtrNotNull(tc, find_key(a, 41));
|
CuAssertPtrNotNull(tc, find_key(a, 41));
|
||||||
CuAssertPtrNotNull(tc, find_key(a, 42));
|
CuAssertPtrNotNull(tc, find_key(a, 42));
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
#define OWNER_3_VERSION 349 /* regions store last owner, not last alliance */
|
#define OWNER_3_VERSION 349 /* regions store last owner, not last alliance */
|
||||||
#define ATTRIBOWNER_VERSION 350 /* all attrib_type functions know who owns the attribute */
|
#define ATTRIBOWNER_VERSION 350 /* all attrib_type functions know who owns the attribute */
|
||||||
#define CRYPT_VERSION 351 /* passwords are encrypted */
|
#define CRYPT_VERSION 351 /* passwords are encrypted */
|
||||||
#define RELEASE_VERSION CRYPT_VERSION /* current datafile */
|
#define ATHASH_VERSION 352 /* attribute-type hash, not name */
|
||||||
|
#define RELEASE_VERSION ATHASH_VERSION /* current datafile */
|
||||||
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
|
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
|
||||||
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
||||||
|
|
||||||
|
|
|
@ -276,15 +276,79 @@ int a_age(attrib ** p, void *owner)
|
||||||
|
|
||||||
static critbit_tree cb_deprecated = { 0 };
|
static critbit_tree cb_deprecated = { 0 };
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct deprecated_s {
|
||||||
|
unsigned int hash;
|
||||||
|
int(*reader)(attrib *, void *, struct storage *);
|
||||||
|
} deprecated_t;
|
||||||
|
|
||||||
void at_deprecate(const char * name, int(*reader)(attrib *, void *, struct storage *))
|
void at_deprecate(const char * name, int(*reader)(attrib *, void *, struct storage *))
|
||||||
{
|
{
|
||||||
char buffer[64];
|
deprecated_t value;
|
||||||
size_t len = strlen(name);
|
|
||||||
len = cb_new_kv(name, len, &reader, sizeof(reader), buffer);
|
value.hash = __at_hashkey(name);
|
||||||
cb_insert(&cb_deprecated, buffer, len);
|
value.reader = reader;
|
||||||
|
cb_insert(&cb_deprecated, &value, sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
int a_read(struct storage *store, attrib ** attribs, void *owner)
|
static int a_read_i(struct storage *store, attrib ** attribs, void *owner, unsigned int key) {
|
||||||
|
int retval = AT_READ_FAIL;
|
||||||
|
int(*reader)(attrib *, void *, struct storage *) = 0;
|
||||||
|
attrib_type *at = at_find(key);
|
||||||
|
attrib * na = 0;
|
||||||
|
|
||||||
|
if (at) {
|
||||||
|
reader = at->read;
|
||||||
|
na = a_new(at);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
void *match;
|
||||||
|
if (cb_find_prefix(&cb_deprecated, &key, sizeof(key), &match, 1, 0)>0) {
|
||||||
|
deprecated_t *value = (deprecated_t *)match;
|
||||||
|
reader = value->reader;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log_error("unknown attribute hash: %u\n", key);
|
||||||
|
assert(at || !"attribute not registered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reader) {
|
||||||
|
retval = reader(na, owner, store);
|
||||||
|
if (na) {
|
||||||
|
switch (retval) {
|
||||||
|
case AT_READ_OK:
|
||||||
|
a_add(attribs, na);
|
||||||
|
break;
|
||||||
|
case AT_READ_FAIL:
|
||||||
|
a_free(na);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"invalid return value");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(!"error: no registered callback can read attribute");
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int a_read(struct storage *store, attrib ** attribs, void *owner) {
|
||||||
|
int key, retval = AT_READ_OK;
|
||||||
|
char zText[128];
|
||||||
|
|
||||||
|
zText[0] = 0;
|
||||||
|
key = -1;
|
||||||
|
READ_INT(store, &key);
|
||||||
|
while (key > 0 && retval == AT_READ_OK) {
|
||||||
|
retval = a_read_i(store, attribs, owner, key);
|
||||||
|
READ_INT(store, &key);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int a_read_orig(struct storage *store, attrib ** attribs, void *owner)
|
||||||
{
|
{
|
||||||
int key, retval = AT_READ_OK;
|
int key, retval = AT_READ_OK;
|
||||||
char zText[128];
|
char zText[128];
|
||||||
|
@ -292,52 +356,14 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
|
||||||
zText[0] = 0;
|
zText[0] = 0;
|
||||||
key = -1;
|
key = -1;
|
||||||
READ_TOK(store, zText, sizeof(zText));
|
READ_TOK(store, zText, sizeof(zText));
|
||||||
if (strcmp(zText, "end") == 0)
|
if (strcmp(zText, "end") == 0) {
|
||||||
return retval;
|
return retval;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
key = __at_hashkey(zText);
|
key = __at_hashkey(zText);
|
||||||
|
}
|
||||||
while (key != -1) {
|
while (key > 0) {
|
||||||
int(*reader)(attrib *, void *, struct storage *) = 0;
|
retval = a_read_i(store, attribs, owner, key);
|
||||||
attrib_type *at = at_find(key);
|
|
||||||
attrib * na = 0;
|
|
||||||
|
|
||||||
if (at) {
|
|
||||||
reader = at->read;
|
|
||||||
na = a_new(at);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
void * kv = 0;
|
|
||||||
cb_find_prefix(&cb_deprecated, zText, strlen(zText) + 1, &kv, 1, 0);
|
|
||||||
if (kv) {
|
|
||||||
cb_get_kv(kv, &reader, sizeof(reader));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "attribute hash: %d (%s)\n", key, zText);
|
|
||||||
assert(at || !"attribute not registered");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reader) {
|
|
||||||
int i = reader(na, owner, store);
|
|
||||||
if (na) {
|
|
||||||
switch (i) {
|
|
||||||
case AT_READ_OK:
|
|
||||||
a_add(attribs, na);
|
|
||||||
break;
|
|
||||||
case AT_READ_FAIL:
|
|
||||||
retval = AT_READ_FAIL;
|
|
||||||
a_free(na);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(!"invalid return value");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(!"error: no registered callback can read attribute");
|
|
||||||
}
|
|
||||||
|
|
||||||
READ_TOK(store, zText, sizeof(zText));
|
READ_TOK(store, zText, sizeof(zText));
|
||||||
if (!strcmp(zText, "end"))
|
if (!strcmp(zText, "end"))
|
||||||
break;
|
break;
|
||||||
|
@ -346,7 +372,24 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void a_write(struct storage *store, const attrib * attribs, const void *owner)
|
void a_write(struct storage *store, const attrib * attribs, const void *owner) {
|
||||||
|
const attrib *na = attribs;
|
||||||
|
|
||||||
|
while (na) {
|
||||||
|
if (na->type->write) {
|
||||||
|
assert(na->type->hashkey || !"attribute not registered");
|
||||||
|
WRITE_INT(store, na->type->hashkey);
|
||||||
|
na->type->write(na, owner, store);
|
||||||
|
na = na->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
na = na->nexttype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WRITE_INT(store, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void a_write_orig(struct storage *store, const attrib * attribs, const void *owner)
|
||||||
{
|
{
|
||||||
const attrib *na = attribs;
|
const attrib *na = attribs;
|
||||||
|
|
||||||
|
|
|
@ -72,11 +72,13 @@ extern "C" {
|
||||||
extern int a_remove(attrib ** pa, attrib * at);
|
extern int a_remove(attrib ** pa, attrib * at);
|
||||||
extern void a_removeall(attrib ** a, const attrib_type * at);
|
extern void a_removeall(attrib ** a, const attrib_type * at);
|
||||||
extern attrib *a_new(const attrib_type * at);
|
extern attrib *a_new(const attrib_type * at);
|
||||||
|
int a_age(attrib ** attribs, void *owner);
|
||||||
|
|
||||||
extern int a_age(attrib ** attribs, void *owner);
|
int a_read_orig(struct storage *store, attrib ** attribs, void *owner);
|
||||||
extern int a_read(struct storage *store, attrib ** attribs, void *owner);
|
void a_write_orig(struct storage *store, const attrib * attribs, const void *owner);
|
||||||
extern void a_write(struct storage *store, const attrib * attribs,
|
|
||||||
const void *owner);
|
int a_read(struct storage *store, attrib ** attribs, void *owner);
|
||||||
|
void a_write(struct storage *store, const attrib * attribs, const void *owner);
|
||||||
|
|
||||||
void free_attribs(void);
|
void free_attribs(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue