forked from github/server
Merge pull request #473 from ennorehling/develop
attribute storage: reduce datafile size by 5%
This commit is contained in:
commit
337aaa18e4
|
@ -59,11 +59,16 @@ local function write_emails(locales)
|
|||
end
|
||||
end
|
||||
|
||||
local function join_path(a, b)
|
||||
if a then return a .. '/' .. b end
|
||||
return b
|
||||
end
|
||||
|
||||
local function write_addresses()
|
||||
local file
|
||||
local faction
|
||||
|
||||
file = io.open(config.basepath .. "/adressen", "w")
|
||||
file = io.open(join_path(config.basepath, "adressen"), "w")
|
||||
for faction in factions() do
|
||||
-- print(faction.id .. " - " .. faction.locale)
|
||||
file:write(tostring(faction) .. ":" .. faction.email .. ":" .. faction.info .. "\n")
|
||||
|
@ -76,7 +81,7 @@ local function write_aliases()
|
|||
local file
|
||||
local faction
|
||||
|
||||
file = io.open(config.basepath .. "/aliases", "w")
|
||||
file = io.open(join_path(config.basepath, "aliases"), "w")
|
||||
for faction in factions() do
|
||||
local unit
|
||||
if faction.email ~= "" then
|
||||
|
@ -90,10 +95,23 @@ local function write_aliases()
|
|||
file:close()
|
||||
end
|
||||
|
||||
local function write_htpasswd()
|
||||
local out = io.open(join_path(config.basepath, "htpasswd"), "w")
|
||||
if out then
|
||||
for f in factions() do
|
||||
if f.password then
|
||||
out:write(itoa36(f.id) .. ":" .. f.password .. "\n")
|
||||
end
|
||||
end
|
||||
out:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function write_files(locales)
|
||||
write_passwords()
|
||||
write_reports()
|
||||
write_summary()
|
||||
write_htpasswd()
|
||||
-- write_passwords()
|
||||
write_reports()
|
||||
write_summary()
|
||||
end
|
||||
|
||||
local function write_scores()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
PROJECT(attributes C)
|
||||
SET(_TEST_FILES
|
||||
stealth.test.c
|
||||
key.test.c
|
||||
otherfaction.test.c
|
||||
)
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ void register_attributes(void)
|
|||
at_register(&at_raceprefix);
|
||||
at_register(&at_iceberg);
|
||||
at_register(&at_key);
|
||||
at_register(&at_keys);
|
||||
at_register(&at_follow);
|
||||
at_register(&at_targetregion);
|
||||
at_register(&at_orcification);
|
||||
|
|
|
@ -30,6 +30,7 @@ attrib_type at_iceberg = {
|
|||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,69 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include <kernel/save.h>
|
||||
#include <util/attrib.h>
|
||||
#include <storage.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void a_writekeys(const attrib *a, const void *o, storage *store) {
|
||||
int i, *keys = (int *)a->data.v;
|
||||
for (i = 0; i <= keys[0]; ++i) {
|
||||
WRITE_INT(store, keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int a_readkeys(attrib * a, void *owner, struct storage *store) {
|
||||
int i, *p = 0;
|
||||
READ_INT(store, &i);
|
||||
assert(i < 4096 && i>0);
|
||||
a->data.v = p = malloc(sizeof(int)*(i + 1));
|
||||
*p++ = i;
|
||||
while (i--) {
|
||||
READ_INT(store, p++);
|
||||
}
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
static int a_readkey(attrib *a, void *owner, struct storage *store) {
|
||||
int res = a_readint(a, owner, store);
|
||||
return (res != AT_READ_FAIL) ? AT_READ_DEPR : res;
|
||||
}
|
||||
|
||||
attrib_type at_keys = {
|
||||
"keys",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
a_writekeys,
|
||||
a_readkeys,
|
||||
NULL
|
||||
};
|
||||
|
||||
void a_upgradekeys(attrib **alist, attrib *abegin) {
|
||||
int n = 0, *keys = 0;
|
||||
int i = 0, val[4];
|
||||
attrib *a, *ak = a_find(*alist, &at_keys);
|
||||
if (!ak) {
|
||||
ak = a_add(alist, a_new(&at_keys));
|
||||
keys = (int *)ak->data.v;
|
||||
n = keys ? keys[0] : 0;
|
||||
}
|
||||
for (a = abegin; a && a->type == abegin->type; a = a->next) {
|
||||
val[i++] = a->data.i;
|
||||
if (i == 4) {
|
||||
keys = realloc(keys, sizeof(int) * (n + i + 1));
|
||||
memcpy(keys + n + 1, val, sizeof(int)*i);
|
||||
n += i;
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
keys = realloc(keys, sizeof(int) * (n + i + 1));
|
||||
memcpy(keys + n + 1, val, sizeof(int)*i);
|
||||
}
|
||||
keys[0] = n + i;
|
||||
}
|
||||
|
||||
attrib_type at_key = {
|
||||
"key",
|
||||
|
@ -29,29 +92,61 @@ attrib_type at_key = {
|
|||
NULL,
|
||||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
a_readkey,
|
||||
a_upgradekeys
|
||||
};
|
||||
|
||||
attrib *add_key(attrib ** alist, int key)
|
||||
void key_set(attrib ** alist, int key)
|
||||
{
|
||||
attrib *a = find_key(*alist, key);
|
||||
if (a == NULL)
|
||||
a = a_add(alist, make_key(key));
|
||||
return a;
|
||||
}
|
||||
|
||||
attrib *make_key(int key)
|
||||
{
|
||||
attrib *a = a_new(&at_key);
|
||||
a->data.i = key;
|
||||
return a;
|
||||
}
|
||||
|
||||
attrib *find_key(attrib * alist, int key)
|
||||
{
|
||||
attrib *a = a_find(alist, &at_key);
|
||||
while (a && a->type == &at_key && a->data.i != key) {
|
||||
a = a->next;
|
||||
int *keys, n = 1;
|
||||
attrib *a;
|
||||
assert(key != 0);
|
||||
a = a_find(*alist, &at_keys);
|
||||
if (!a) {
|
||||
a = a_add(alist, a_new(&at_keys));
|
||||
}
|
||||
return (a && a->type == &at_key) ? a : NULL;
|
||||
keys = (int *)a->data.v;
|
||||
if (keys) {
|
||||
n = keys[0] + 1;
|
||||
}
|
||||
keys = realloc(keys, sizeof(int) *(n + 1));
|
||||
// TODO: does insertion sort pay off here?
|
||||
keys[0] = n;
|
||||
keys[n] = key;
|
||||
a->data.v = keys;
|
||||
}
|
||||
|
||||
void key_unset(attrib ** alist, int key)
|
||||
{
|
||||
attrib *a;
|
||||
assert(key != 0);
|
||||
a = a_find(*alist, &at_keys);
|
||||
if (a) {
|
||||
int i, *keys = (int *)a->data.v;
|
||||
if (keys) {
|
||||
for (i = 1; i <= keys[0]; ++i) {
|
||||
if (keys[i] == key) {
|
||||
keys[i] = keys[keys[0]];
|
||||
keys[0]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool key_get(attrib *alist, int key) {
|
||||
attrib *a;
|
||||
assert(key != 0);
|
||||
a = a_find(alist, &at_keys);
|
||||
if (a) {
|
||||
int i, *keys = (int *)a->data.v;
|
||||
if (keys) {
|
||||
for (i = 1; i <= keys[0]; ++i) {
|
||||
if (keys[i] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,12 +21,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct attrib;
|
||||
struct attrib_type;
|
||||
extern struct attrib_type at_key;
|
||||
extern struct attrib_type at_keys;
|
||||
|
||||
struct attrib *make_key(int key);
|
||||
struct attrib *find_key(struct attrib *alist, int key);
|
||||
struct attrib *add_key(struct attrib **alist, int key);
|
||||
void key_set(struct attrib **alist, int key);
|
||||
void key_unset(struct attrib **alist, int key);
|
||||
bool key_get(struct attrib *alist, int key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#include <platform.h>
|
||||
#include "key.h"
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <CuTest.h>
|
||||
|
||||
static void test_get_set_keys(CuTest *tc) {
|
||||
attrib *a = 0;
|
||||
key_set(&a, 42);
|
||||
key_set(&a, 43);
|
||||
key_set(&a, 44);
|
||||
CuAssertTrue(tc, key_get(a, 42));
|
||||
CuAssertTrue(tc, key_get(a, 43));
|
||||
CuAssertTrue(tc, key_get(a, 44));
|
||||
key_unset(&a, 42);
|
||||
CuAssertTrue(tc, !key_get(a, 42));
|
||||
CuAssertTrue(tc, key_get(a, 43));
|
||||
CuAssertTrue(tc, key_get(a, 44));
|
||||
a_removeall(&a, NULL);
|
||||
}
|
||||
|
||||
CuSuite *get_key_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_get_set_keys);
|
||||
return suite;
|
||||
}
|
|
@ -28,6 +28,7 @@ attrib_type at_matmod = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ATF_PRESERVE
|
||||
};
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
*/
|
||||
|
||||
attrib_type at_orcification = {
|
||||
"orcification", NULL, NULL, NULL, a_writeint, a_readint, ATF_UNIQUE
|
||||
"orcification", NULL, NULL, NULL, a_writeint, a_readint, NULL, ATF_UNIQUE
|
||||
};
|
||||
|
||||
attrib *make_orcification(int orcification)
|
||||
|
|
|
@ -53,7 +53,7 @@ int read_of(struct attrib *a, void *owner, struct storage *store)
|
|||
}
|
||||
|
||||
attrib_type at_otherfaction = {
|
||||
"otherfaction", NULL, NULL, NULL, write_of, read_of, ATF_UNIQUE
|
||||
"otherfaction", NULL, NULL, NULL, write_of, read_of, NULL, ATF_UNIQUE
|
||||
};
|
||||
|
||||
struct faction *get_otherfaction(const struct attrib *a)
|
||||
|
|
|
@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <stdlib.h>
|
||||
|
||||
attrib_type at_raceprefix = {
|
||||
"raceprefix", NULL, a_finalizestring, NULL, a_writestring, a_readstring,
|
||||
"raceprefix", NULL, a_finalizestring, NULL, a_writestring, a_readstring, NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ attrib_type at_reduceproduction = {
|
|||
age_reduceproduction,
|
||||
a_writeshorts,
|
||||
a_readshorts,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ attrib_type at_targetregion = {
|
|||
NULL,
|
||||
write_targetregion,
|
||||
read_targetregion,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -542,11 +542,9 @@ static int tolua_region_getkey(lua_State * L)
|
|||
{
|
||||
region *self = (region *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
lua_pushboolean(L, a != NULL);
|
||||
|
||||
lua_pushboolean(L, key_get(self->attribs, flag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -555,14 +553,13 @@ static int tolua_region_setkey(lua_State * L)
|
|||
region *self = (region *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
int value = tolua_toboolean(L, 3, 0);
|
||||
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
if (a == NULL && value) {
|
||||
add_key(&self->attribs, flag);
|
||||
|
||||
if (value) {
|
||||
key_set(&self->attribs, flag);
|
||||
}
|
||||
else if (a != NULL && !value) {
|
||||
a_remove(&self->attribs, a);
|
||||
else {
|
||||
key_unset(&self->attribs, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -807,8 +807,7 @@ static int tolua_unit_get_flag(lua_State * L)
|
|||
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
||||
const char *name = tolua_tostring(L, 2, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
lua_pushboolean(L, (a != NULL));
|
||||
lua_pushboolean(L, key_get(self->attribs, flag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -818,12 +817,11 @@ static int tolua_unit_set_flag(lua_State * L)
|
|||
const char *name = tolua_tostring(L, 2, 0);
|
||||
int value = (int)tolua_tonumber(L, 3, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(self->attribs, flag);
|
||||
if (a == NULL && value) {
|
||||
add_key(&self->attribs, flag);
|
||||
if (value) {
|
||||
key_set(&self->attribs, flag);
|
||||
}
|
||||
else if (a != NULL && !value) {
|
||||
a_remove(&self->attribs, a);
|
||||
else {
|
||||
key_unset(&self->attribs, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ TOLUA_PKG(game);
|
|||
int log_lua_error(lua_State * L)
|
||||
{
|
||||
const char *error = lua_tostring(L, -1);
|
||||
log_fatal("LUA call failed.\n%s\n", error);
|
||||
log_fatal("Lua call failed.\n%s\n", error);
|
||||
lua_pop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
@ -186,8 +186,8 @@ static int tolua_getkey(lua_State * L)
|
|||
{
|
||||
const char *name = tolua_tostring(L, 1, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(global.attribs, flag);
|
||||
lua_pushboolean(L, a != NULL);
|
||||
|
||||
lua_pushboolean(L, key_get(global.attribs, flag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -209,12 +209,11 @@ static int tolua_setkey(lua_State * L)
|
|||
const char *name = tolua_tostring(L, 1, 0);
|
||||
int value = tolua_toboolean(L, 2, 0);
|
||||
int flag = atoi36(name);
|
||||
attrib *a = find_key(global.attribs, flag);
|
||||
if (a == NULL && value) {
|
||||
add_key(&global.attribs, flag);
|
||||
if (value) {
|
||||
key_set(&global.attribs, flag);
|
||||
}
|
||||
else if (a != NULL && !value) {
|
||||
a_remove(&global.attribs, a);
|
||||
else {
|
||||
key_unset(&global.attribs, flag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1184,6 +1183,7 @@ int eressea_run(lua_State *L, const char *luafile)
|
|||
err = lua_pcall(L, 1, 1, -3);
|
||||
if (err != 0) {
|
||||
log_lua_error(L);
|
||||
assert(!"Lua syntax error? check log.");
|
||||
}
|
||||
else {
|
||||
if (lua_isnumber(L, -1)) {
|
||||
|
|
|
@ -50,6 +50,7 @@ attrib_type at_chaoscount = {
|
|||
DEFAULT_AGE,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ attrib_type at_guard = {
|
|||
DEFAULT_AGE,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -480,7 +480,7 @@ int victorycondition(const alliance * al, const char *name)
|
|||
|
||||
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
|
||||
faction *f = (faction *)ql_get(flist, qi);
|
||||
if (find_key(f->attribs, atoi36("phnx"))) {
|
||||
if (key_get(f->attribs, atoi36("phnx"))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ int victorycondition(const alliance * al, const char *name)
|
|||
|
||||
for (qi = 0; flist; ql_advance(&flist, &qi, 1)) {
|
||||
faction *f = (faction *)ql_get(flist, qi);
|
||||
if (find_key(f->attribs, atoi36("pyra"))) {
|
||||
if (key_get(f->attribs, atoi36("pyra"))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ attrib_type at_npcfaction = {
|
|||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ int buildingcapacity(const building * b)
|
|||
}
|
||||
|
||||
attrib_type at_building_generic_type = {
|
||||
"building_generic_type", NULL, NULL, NULL, a_writestring, a_readstring,
|
||||
"building_generic_type", NULL, NULL, NULL, a_writestring, a_readstring, NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -659,7 +659,7 @@ int read_borders(struct storage *store)
|
|||
type->read(b, store);
|
||||
if (global.data_version < NOBORDERATTRIBS_VERSION) {
|
||||
attrib *a = NULL;
|
||||
int result = a_read(store, &a, b);
|
||||
int result = read_attribs(store, &a, b);
|
||||
if (border_convert_cb) {
|
||||
border_convert_cb(b, a);
|
||||
}
|
||||
|
|
|
@ -285,6 +285,7 @@ attrib_type at_curse = {
|
|||
curse_age,
|
||||
curse_write,
|
||||
curse_read,
|
||||
NULL,
|
||||
ATF_CURSE
|
||||
};
|
||||
|
||||
|
|
|
@ -798,6 +798,7 @@ attrib_type at_maxmagicians = {
|
|||
NULL,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ write_group(const attrib * a, const void *owner, struct storage *store)
|
|||
attrib_type at_group = { /* attribute for units assigned to a group */
|
||||
"grp",
|
||||
DEFAULT_INIT,
|
||||
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, ATF_UNIQUE };
|
||||
DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, NULL, ATF_UNIQUE };
|
||||
|
||||
void free_group(group * g)
|
||||
{
|
||||
|
@ -209,7 +209,7 @@ void write_groups(struct storage *store, const faction * f)
|
|||
}
|
||||
}
|
||||
WRITE_INT(store, 0);
|
||||
a_write(store, g->attribs, g);
|
||||
write_attribs(store, g->attribs, g);
|
||||
WRITE_SECTION(store);
|
||||
}
|
||||
WRITE_INT(store, 0);
|
||||
|
@ -241,6 +241,6 @@ void read_groups(struct storage *store, faction * f)
|
|||
if (!a->faction)
|
||||
ur_add(fid, &a->faction, resolve_faction);
|
||||
}
|
||||
a_read(store, &g->attribs, g);
|
||||
read_attribs(store, &g->attribs, g);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -926,14 +926,14 @@ struct order *ord)
|
|||
"unit item region command", user, itype->rtype, user->region, ord));
|
||||
return -1;
|
||||
}
|
||||
if (!is_mage(user) || find_key(f->attribs, atoi36("mbst")) != NULL) {
|
||||
if (!is_mage(user) || key_get(f->attribs, atoi36("mbst"))) {
|
||||
cmistake(user, user->thisorder, 214, MSG_EVENT);
|
||||
return -1;
|
||||
}
|
||||
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
|
||||
user->number);
|
||||
|
||||
a_add(&f->attribs, make_key(atoi36("mbst")));
|
||||
key_set(&f->attribs, atoi36("mbst"));
|
||||
set_level(user, SK_MAGIC, 3);
|
||||
|
||||
ADDMSG(&user->faction->msgs, msg_message("use_item",
|
||||
|
|
|
@ -483,6 +483,7 @@ attrib_type at_horseluck = {
|
|||
DEFAULT_AGE,
|
||||
NO_WRITE,
|
||||
NO_READ,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -496,6 +497,7 @@ attrib_type at_peasantluck = {
|
|||
DEFAULT_AGE,
|
||||
NO_WRITE,
|
||||
NO_READ,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -509,6 +511,7 @@ attrib_type at_deathcount = {
|
|||
DEFAULT_AGE,
|
||||
a_writeint,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -522,6 +525,7 @@ attrib_type at_woodcount = {
|
|||
DEFAULT_AGE,
|
||||
NO_WRITE,
|
||||
a_readint,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -577,6 +577,24 @@ const struct locale *lang)
|
|||
WRITE_STR(data->store, obuf);
|
||||
}
|
||||
|
||||
int read_attribs(storage *store, attrib **alist, void *owner) {
|
||||
if (global.data_version < ATHASH_VERSION) {
|
||||
return a_read_orig(store, alist, owner);
|
||||
}
|
||||
else {
|
||||
return a_read(store, alist, owner);
|
||||
}
|
||||
}
|
||||
|
||||
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 *u;
|
||||
|
@ -748,8 +766,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);
|
||||
u->hp = u->number;
|
||||
}
|
||||
|
||||
a_read(data->store, &u->attribs, u);
|
||||
read_attribs(data->store, &u->attribs, u);
|
||||
return u;
|
||||
}
|
||||
|
||||
|
@ -823,7 +840,7 @@ void write_unit(struct gamedata *data, const unit * u)
|
|||
}
|
||||
WRITE_INT(data->store, u->hp);
|
||||
WRITE_SECTION(data->store);
|
||||
a_write(data->store, u->attribs, u);
|
||||
write_attribs(data->store, u->attribs, u);
|
||||
WRITE_SECTION(data->store);
|
||||
}
|
||||
|
||||
|
@ -982,7 +999,7 @@ static region *readregion(struct gamedata *data, int x, int y)
|
|||
read_owner(data, &r->land->ownership);
|
||||
}
|
||||
}
|
||||
a_read(data->store, &r->attribs, r);
|
||||
read_attribs(data->store, &r->attribs, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1063,7 @@ void writeregion(struct gamedata *data, const region * r)
|
|||
WRITE_SECTION(data->store);
|
||||
#endif
|
||||
}
|
||||
a_write(data->store, r->attribs, r);
|
||||
write_attribs(data->store, r->attribs, r);
|
||||
WRITE_SECTION(data->store);
|
||||
}
|
||||
|
||||
|
@ -1253,7 +1270,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);
|
||||
for (;;) {
|
||||
READ_TOK(data->store, name, sizeof(name));
|
||||
|
@ -1338,7 +1355,7 @@ void writefaction(struct gamedata *data, const faction * f)
|
|||
WRITE_INT(data->store, f->magiegebiet);
|
||||
|
||||
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_items(data->store, f->items);
|
||||
WRITE_SECTION(data->store);
|
||||
|
@ -1451,7 +1468,7 @@ int readgame(const char *filename, bool backup)
|
|||
else {
|
||||
READ_STR(&store, NULL, 0);
|
||||
}
|
||||
a_read(&store, &global.attribs, NULL);
|
||||
read_attribs(&store, &global.attribs, NULL);
|
||||
READ_INT(&store, &turn);
|
||||
global.data_turn = turn;
|
||||
log_debug(" - reading turn %d\n", turn);
|
||||
|
@ -1512,7 +1529,7 @@ int readgame(const char *filename, bool backup)
|
|||
fno = read_faction_reference(&store);
|
||||
}
|
||||
}
|
||||
a_read(&store, &pl->attribs, pl);
|
||||
read_attribs(&store, &pl->attribs, pl);
|
||||
if (pl->id != 1094969858) { // Regatta
|
||||
addlist(&planes, pl);
|
||||
}
|
||||
|
@ -1580,7 +1597,7 @@ int readgame(const char *filename, bool backup)
|
|||
READ_STR(&store, name, sizeof(name));
|
||||
b->type = bt_find(name);
|
||||
b->region = r;
|
||||
a_read(&store, &b->attribs, b);
|
||||
read_attribs(&store, &b->attribs, b);
|
||||
if (b->type == bt_lighthouse) {
|
||||
r->flags |= RF_LIGHTHOUSE;
|
||||
}
|
||||
|
@ -1627,7 +1644,7 @@ int readgame(const char *filename, bool backup)
|
|||
if (sh->type->flags & SFL_NOCOAST) {
|
||||
sh->coast = NODIRECTION;
|
||||
}
|
||||
a_read(&store, &sh->attribs, sh);
|
||||
read_attribs(&store, &sh->attribs, sh);
|
||||
}
|
||||
|
||||
*shp = 0;
|
||||
|
@ -1777,7 +1794,7 @@ int writegame(const char *filename)
|
|||
WRITE_INT(&store, game_id());
|
||||
WRITE_SECTION(&store);
|
||||
|
||||
a_write(&store, global.attribs, NULL);
|
||||
write_attribs(&store, global.attribs, NULL);
|
||||
WRITE_SECTION(&store);
|
||||
|
||||
WRITE_INT(&store, turn);
|
||||
|
@ -1807,7 +1824,7 @@ int writegame(const char *filename)
|
|||
w = w->next;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1852,7 +1869,7 @@ int writegame(const char *filename)
|
|||
WRITE_INT(&store, b->size);
|
||||
WRITE_TOK(&store, b->type->_name);
|
||||
WRITE_SECTION(&store);
|
||||
a_write(&store, b->attribs, b);
|
||||
write_attribs(&store, b->attribs, b);
|
||||
WRITE_SECTION(&store);
|
||||
}
|
||||
|
||||
|
@ -1870,7 +1887,7 @@ int writegame(const char *filename)
|
|||
assert((sh->type->flags & SFL_NOCOAST) == 0 || sh->coast == NODIRECTION);
|
||||
WRITE_INT(&store, sh->coast);
|
||||
WRITE_SECTION(&store);
|
||||
a_write(&store, sh->attribs, sh);
|
||||
write_attribs(&store, sh->attribs, sh);
|
||||
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 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);
|
||||
struct unit *read_unit(struct gamedata *data);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
#include <util/attrib.h>
|
||||
#include <attributes/key.h>
|
||||
|
||||
#include "save.h"
|
||||
#include "unit.h"
|
||||
|
@ -61,9 +63,37 @@ static void test_readwrite_unit(CuTest * tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_readwrite_attrib(CuTest *tc) {
|
||||
gamedata *data;
|
||||
attrib *a = NULL;
|
||||
const char *path = "attrib.dat";
|
||||
test_cleanup();
|
||||
global.data_version = RELEASE_VERSION; // FIXME: hack!
|
||||
data = gamedata_open(path, "wb");
|
||||
CuAssertPtrNotNull(tc, data);
|
||||
key_set(&a, 41);
|
||||
key_set(&a, 42);
|
||||
write_attribs(data->store, a, NULL);
|
||||
gamedata_close(data);
|
||||
a_removeall(&a, NULL);
|
||||
CuAssertPtrEquals(tc, 0, a);
|
||||
|
||||
data = gamedata_open(path, "rb");
|
||||
CuAssertPtrNotNull(tc, data);
|
||||
read_attribs(data->store, &a, NULL);
|
||||
gamedata_close(data);
|
||||
CuAssertTrue(tc, key_get(a, 41));
|
||||
CuAssertTrue(tc, key_get(a, 42));
|
||||
a_removeall(&a, NULL);
|
||||
|
||||
CuAssertIntEquals(tc, 0, remove(path));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_save_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_readwrite_attrib);
|
||||
SUITE_ADD_TEST(suite, test_readwrite_data);
|
||||
SUITE_ADD_TEST(suite, test_readwrite_unit);
|
||||
return suite;
|
||||
|
|
|
@ -59,6 +59,7 @@ attrib_type at_skillmod = {
|
|||
NULL,
|
||||
NULL, /* can't write function pointers */
|
||||
NULL, /* can't read function pointers */
|
||||
NULL,
|
||||
ATF_PRESERVE
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
#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 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 MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */
|
||||
|
||||
|
|
|
@ -486,6 +486,7 @@ attrib_type at_germs = {
|
|||
DEFAULT_AGE,
|
||||
a_writeshorts,
|
||||
a_readshorts,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -2749,7 +2750,7 @@ void sinkships(struct region * r)
|
|||
|
||||
static attrib_type at_number = {
|
||||
"faction_renum",
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -335,6 +335,7 @@ attrib_type at_mage = {
|
|||
NULL,
|
||||
write_mage,
|
||||
read_mage,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -2416,6 +2417,7 @@ attrib_type at_familiarmage = {
|
|||
age_unit,
|
||||
a_write_unit,
|
||||
read_magician,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -2426,6 +2428,7 @@ attrib_type at_familiar = {
|
|||
age_unit,
|
||||
a_write_unit,
|
||||
read_familiar,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -2436,6 +2439,7 @@ attrib_type at_clonemage = {
|
|||
age_unit,
|
||||
a_write_unit,
|
||||
read_magician,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
@ -2446,6 +2450,7 @@ attrib_type at_clone = {
|
|||
age_unit,
|
||||
a_write_unit,
|
||||
read_clone,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ static void free_market(attrib * a)
|
|||
attrib_type at_market = {
|
||||
"script",
|
||||
NULL, free_market, NULL,
|
||||
NULL, NULL, ATF_UNIQUE
|
||||
NULL, NULL, NULL, ATF_UNIQUE
|
||||
};
|
||||
|
||||
static int rc_luxury_trade(const struct race *rc)
|
||||
|
|
|
@ -194,7 +194,7 @@ void warden_add_give(unit * src, unit * u, const item_type * itype, int n)
|
|||
|
||||
void create_museum(void)
|
||||
{
|
||||
#if 0 /* TODO: move this to LUA. It should be possible. */
|
||||
#if 0 /* TODO: move this to Lua. It should be possible. */
|
||||
unsigned int museum_id = hashstring("museum");
|
||||
plane *museum = getplanebyid(museum_id);
|
||||
region *r;
|
||||
|
|
|
@ -96,6 +96,7 @@ static attrib_type at_alp = {
|
|||
alp_verify,
|
||||
alp_write,
|
||||
alp_read,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ static attrib_type at_cursewall = {
|
|||
curse_age,
|
||||
cw_write,
|
||||
cw_read,
|
||||
NULL,
|
||||
ATF_CURSE
|
||||
};
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ static void done_learning(struct attrib *a)
|
|||
|
||||
const attrib_type at_learning = {
|
||||
"learning",
|
||||
init_learning, done_learning, NULL, NULL, NULL,
|
||||
init_learning, done_learning, NULL, NULL, NULL, NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ int RunAllTests(int argc, char *argv[])
|
|||
ADD_SUITE(monsters);
|
||||
ADD_SUITE(move);
|
||||
ADD_SUITE(piracy);
|
||||
ADD_SUITE(key);
|
||||
ADD_SUITE(stealth);
|
||||
ADD_SUITE(otherfaction);
|
||||
ADD_SUITE(upkeep);
|
||||
|
|
|
@ -209,28 +209,37 @@ int a_remove(attrib ** pa, attrib * a)
|
|||
void a_removeall(attrib ** pa, const attrib_type * at)
|
||||
{
|
||||
attrib **pnexttype = pa;
|
||||
attrib **pnext = NULL;
|
||||
|
||||
while (*pnexttype) {
|
||||
attrib *next = *pnexttype;
|
||||
if (next->type == at)
|
||||
break;
|
||||
pnexttype = &next->nexttype;
|
||||
pnext = &next->next;
|
||||
}
|
||||
if (*pnexttype && (*pnexttype)->type == at) {
|
||||
attrib *a = *pnexttype;
|
||||
|
||||
*pnexttype = a->nexttype;
|
||||
if (pnext) {
|
||||
while (*pnext && (*pnext)->type != at)
|
||||
pnext = &(*pnext)->next;
|
||||
*pnext = a->nexttype;
|
||||
if (!at) {
|
||||
while (*pnexttype) {
|
||||
attrib *a = *pnexttype;
|
||||
*pnexttype = a->next;
|
||||
a_free(a);
|
||||
}
|
||||
while (a && a->type == at) {
|
||||
attrib *ra = a;
|
||||
a = a->next;
|
||||
a_free(ra);
|
||||
}
|
||||
else {
|
||||
attrib **pnext = NULL;
|
||||
while (*pnexttype) {
|
||||
attrib *a = *pnexttype;
|
||||
if (a->type == at)
|
||||
break;
|
||||
pnexttype = &a->nexttype;
|
||||
pnext = &a->next;
|
||||
}
|
||||
if (*pnexttype && (*pnexttype)->type == at) {
|
||||
attrib *a = *pnexttype;
|
||||
|
||||
*pnexttype = a->nexttype;
|
||||
if (pnext) {
|
||||
while (*pnext && (*pnext)->type != at)
|
||||
pnext = &(*pnext)->next;
|
||||
*pnext = a->nexttype;
|
||||
}
|
||||
while (a && a->type == at) {
|
||||
attrib *ra = a;
|
||||
a = a->next;
|
||||
a_free(ra);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,15 +276,92 @@ int a_age(attrib ** p, void *owner)
|
|||
|
||||
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 *))
|
||||
{
|
||||
char buffer[64];
|
||||
size_t len = strlen(name);
|
||||
len = cb_new_kv(name, len, &reader, sizeof(reader), buffer);
|
||||
cb_insert(&cb_deprecated, buffer, len);
|
||||
deprecated_t value;
|
||||
|
||||
value.hash = __at_hashkey(name);
|
||||
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_OK;
|
||||
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) {
|
||||
int ret = reader(na, owner, store);
|
||||
if (na) {
|
||||
switch (ret) {
|
||||
case AT_READ_DEPR:
|
||||
case AT_READ_OK:
|
||||
a_add(attribs, na);
|
||||
retval = ret;
|
||||
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;
|
||||
|
||||
key = -1;
|
||||
READ_INT(store, &key);
|
||||
while (key > 0) {
|
||||
int ret = a_read_i(store, attribs, owner, key);
|
||||
if (ret == AT_READ_DEPR) {
|
||||
retval = AT_READ_DEPR;
|
||||
}
|
||||
READ_INT(store, &key);
|
||||
}
|
||||
if (retval == AT_READ_DEPR) {
|
||||
/* handle deprecated attributes */
|
||||
attrib *a = *attribs;
|
||||
while (a) {
|
||||
if (a->type->upgrade) {
|
||||
a->type->upgrade(attribs, a);
|
||||
}
|
||||
a = a->nexttype;
|
||||
}
|
||||
}
|
||||
return AT_READ_OK;
|
||||
}
|
||||
|
||||
int a_read_orig(struct storage *store, attrib ** attribs, void *owner)
|
||||
{
|
||||
int key, retval = AT_READ_OK;
|
||||
char zText[128];
|
||||
|
@ -283,52 +369,14 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
|
|||
zText[0] = 0;
|
||||
key = -1;
|
||||
READ_TOK(store, zText, sizeof(zText));
|
||||
if (strcmp(zText, "end") == 0)
|
||||
if (strcmp(zText, "end") == 0) {
|
||||
return retval;
|
||||
else
|
||||
}
|
||||
else {
|
||||
key = __at_hashkey(zText);
|
||||
|
||||
while (key != -1) {
|
||||
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 * 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");
|
||||
}
|
||||
|
||||
}
|
||||
while (key > 0) {
|
||||
retval = a_read_i(store, attribs, owner, key);
|
||||
READ_TOK(store, zText, sizeof(zText));
|
||||
if (!strcmp(zText, "end"))
|
||||
break;
|
||||
|
@ -337,7 +385,24 @@ int a_read(struct storage *store, attrib ** attribs, void *owner)
|
|||
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;
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ extern "C" {
|
|||
/* age returns 0 if the attribute needs to be removed, !=0 otherwise */
|
||||
void(*write) (const struct attrib *, const void *owner, struct storage *);
|
||||
int(*read) (struct attrib *, void *owner, struct storage *); /* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
|
||||
void(*upgrade) (struct attrib **alist, struct attrib *a);
|
||||
unsigned int flags;
|
||||
/* ---- internal data, do not modify: ---- */
|
||||
struct attrib_type *nexthash;
|
||||
|
@ -72,11 +73,13 @@ extern "C" {
|
|||
extern int a_remove(attrib ** pa, attrib * at);
|
||||
extern void a_removeall(attrib ** a, 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);
|
||||
extern int a_read(struct storage *store, attrib ** attribs, void *owner);
|
||||
extern void a_write(struct storage *store, const attrib * attribs,
|
||||
const void *owner);
|
||||
int a_read_orig(struct storage *store, attrib ** attribs, void *owner);
|
||||
void a_write_orig(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);
|
||||
|
||||
|
@ -88,6 +91,7 @@ extern "C" {
|
|||
|
||||
#define AT_READ_OK 0
|
||||
#define AT_READ_FAIL -1
|
||||
#define AT_READ_DEPR 1 /* a deprecated attribute was read, should run a_upgrade */
|
||||
|
||||
#define AT_AGE_REMOVE 0 /* remove the attribute after calling age() */
|
||||
#define AT_AGE_KEEP 1 /* keep the attribute for another turn */
|
||||
|
|
|
@ -51,6 +51,23 @@ static void test_attrib_remove_self(CuTest * tc) {
|
|||
CuAssertPtrEquals(tc, a, alist);
|
||||
}
|
||||
|
||||
|
||||
static void test_attrib_removeall(CuTest * tc) {
|
||||
const attrib_type at_foo = { "foo" };
|
||||
const attrib_type at_bar = { "bar" };
|
||||
attrib *alist = 0, *a;
|
||||
a_add(&alist, a_new(&at_foo));
|
||||
a = a_add(&alist, a_new(&at_bar));
|
||||
a_add(&alist, a_new(&at_foo));
|
||||
a_removeall(&alist, &at_foo);
|
||||
CuAssertPtrEquals(tc, a, alist);
|
||||
CuAssertPtrEquals(tc, 0, alist->next);
|
||||
a_add(&alist, a_new(&at_bar));
|
||||
a_add(&alist, a_new(&at_foo));
|
||||
a_removeall(&alist, NULL);
|
||||
CuAssertPtrEquals(tc, 0, alist);
|
||||
}
|
||||
|
||||
static void test_attrib_remove(CuTest * tc)
|
||||
{
|
||||
attrib_type at_foo = { "foo" };
|
||||
|
@ -98,6 +115,7 @@ CuSuite *get_attrib_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_attrib_new);
|
||||
SUITE_ADD_TEST(suite, test_attrib_add);
|
||||
SUITE_ADD_TEST(suite, test_attrib_remove);
|
||||
SUITE_ADD_TEST(suite, test_attrib_removeall);
|
||||
SUITE_ADD_TEST(suite, test_attrib_remove_self);
|
||||
SUITE_ADD_TEST(suite, test_attrib_nexttype);
|
||||
return suite;
|
||||
|
|
|
@ -134,6 +134,7 @@ static attrib_type at_wormhole = {
|
|||
wormhole_age,
|
||||
wormhole_write,
|
||||
wormhole_read,
|
||||
NULL,
|
||||
ATF_UNIQUE
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
NEWFILES="data/185.dat datum parteien parteien.full passwd score turn"
|
||||
NEWFILES="data/185.dat datum parteien parteien.full htpasswd score turn"
|
||||
cleanup () {
|
||||
rm -rf reports $NEWFILES
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ expr=$2
|
|||
expect=$3
|
||||
count=`grep -cE $expr $file`
|
||||
[ $count -eq $expect ] || quit 1 "expected $expect counts of $expr in $file, got $count"
|
||||
echo "PASS: $expr is $expect"
|
||||
}
|
||||
|
||||
ROOT=`pwd`
|
||||
|
@ -34,10 +35,11 @@ VALGRIND=`which valgrind`
|
|||
SERVER=../Debug/eressea/eressea
|
||||
if [ -n "$VALGRIND" ]; then
|
||||
SUPP=../share/ubuntu-12_04.supp
|
||||
SERVER="$VALGRIND --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER"
|
||||
SERVER="$VALGRIND --track-origins=yes --gen-suppressions=all --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER"
|
||||
fi
|
||||
echo "running $SERVER"
|
||||
$SERVER -t 184 ../scripts/run-turn.lua
|
||||
echo "integration tests"
|
||||
[ -d reports ] || quit 4 "no reports directory created"
|
||||
CRFILE=185-zvto.cr
|
||||
for file in $NEWFILES reports/$CRFILE ; do
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
# alliance:factions:persons:score
|
||||
1248287:1:0:0
|
||||
1490214:1:0:2105
|
Loading…
Reference in New Issue