Mercurial > molko
changeset 328:60a4f904da21
rpg: separate property from save
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 04 Oct 2021 13:10:11 +0200 |
parents | 42a6710629f5 |
children | ea4a3af71c18 |
files | src/libmlk-adventure/adventure/action/chest.c src/libmlk-adventure/adventure/action/chest.h src/libmlk-rpg/CMakeLists.txt src/libmlk-rpg/assets/sql/property-get.sql src/libmlk-rpg/assets/sql/property-load.sql src/libmlk-rpg/assets/sql/property-save.sql src/libmlk-rpg/assets/sql/property-set.sql src/libmlk-rpg/rpg/property.c src/libmlk-rpg/rpg/property.h src/libmlk-rpg/rpg/save.c src/libmlk-rpg/rpg/save.h tests/test-save.c |
diffstat | 12 files changed, 210 insertions(+), 210 deletions(-) [+] |
line wrap: on
line diff
--- a/src/libmlk-adventure/adventure/action/chest.c Sun Oct 03 10:31:45 2021 +0200 +++ b/src/libmlk-adventure/adventure/action/chest.c Mon Oct 04 13:10:11 2021 +0200 @@ -29,6 +29,7 @@ #include <rpg/map.h> #include <rpg/save.h> +#include <rpg/property.h> #include "chest.h" @@ -130,7 +131,7 @@ assert(c); if (c->save && c->property) { - if (save_get_property(c->save, c->property) < 0) + if (property_load(c->property, c->save) < 0) panic(); /* TODO: add an utility. */
--- a/src/libmlk-adventure/adventure/action/chest.h Sun Oct 03 10:31:45 2021 +0200 +++ b/src/libmlk-adventure/adventure/action/chest.h Mon Oct 04 13:10:11 2021 +0200 @@ -25,7 +25,7 @@ struct map; struct save; -struct save_property; +struct property; struct sound; enum chest_state { @@ -47,7 +47,7 @@ /* Optional. */ struct save *save; - struct save_property *property; + struct property *property; struct sound *sound; void *data; void (*exec)(struct chest *);
--- a/src/libmlk-rpg/CMakeLists.txt Sun Oct 03 10:31:45 2021 +0200 +++ b/src/libmlk-rpg/CMakeLists.txt Mon Oct 04 13:10:11 2021 +0200 @@ -63,6 +63,8 @@ ${libmlk-rpg_SOURCE_DIR}/rpg/map.h ${libmlk-rpg_SOURCE_DIR}/rpg/message.c ${libmlk-rpg_SOURCE_DIR}/rpg/message.h + ${libmlk-rpg_SOURCE_DIR}/rpg/property.c + ${libmlk-rpg_SOURCE_DIR}/rpg/property.h ${libmlk-rpg_SOURCE_DIR}/rpg/rpg.c ${libmlk-rpg_SOURCE_DIR}/rpg/rpg.h ${libmlk-rpg_SOURCE_DIR}/rpg/rpg_p.h @@ -87,9 +89,9 @@ ${libmlk-rpg_SOURCE_DIR}/assets/sql/character-load.sql ${libmlk-rpg_SOURCE_DIR}/assets/sql/character-save.sql ${libmlk-rpg_SOURCE_DIR}/assets/sql/init.sql - ${libmlk-rpg_SOURCE_DIR}/assets/sql/property-get.sql + ${libmlk-rpg_SOURCE_DIR}/assets/sql/property-load.sql ${libmlk-rpg_SOURCE_DIR}/assets/sql/property-remove.sql - ${libmlk-rpg_SOURCE_DIR}/assets/sql/property-set.sql + ${libmlk-rpg_SOURCE_DIR}/assets/sql/property-save.sql ) set(
--- a/src/libmlk-rpg/assets/sql/property-get.sql Sun Oct 03 10:31:45 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ --- --- property-get.sql -- get a property --- --- Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> --- --- Permission to use, copy, modify, and/or distribute this software for any --- purpose with or without fee is hereby granted, provided that the above --- copyright notice and this permission notice appear in all copies. --- --- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR --- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN --- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF --- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --- - -SELECT value - FROM property - WHERE key = ?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-rpg/assets/sql/property-load.sql Mon Oct 04 13:10:11 2021 +0200 @@ -0,0 +1,21 @@ +-- +-- property-load.sql -- get a property +-- +-- Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> +-- +-- Permission to use, copy, modify, and/or distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +-- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +-- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +-- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +-- + +SELECT value + FROM property + WHERE key = ?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-rpg/assets/sql/property-save.sql Mon Oct 04 13:10:11 2021 +0200 @@ -0,0 +1,26 @@ +-- +-- property-save.sql -- set a property +-- +-- Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> +-- +-- Permission to use, copy, modify, and/or distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +-- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +-- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +-- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +-- + +INSERT OR REPLACE INTO property( + key, + value +) +VALUES( + ?, + ? +)
--- a/src/libmlk-rpg/assets/sql/property-set.sql Sun Oct 03 10:31:45 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ --- --- property-set.sql -- set a property --- --- Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> --- --- Permission to use, copy, modify, and/or distribute this software for any --- purpose with or without fee is hereby granted, provided that the above --- copyright notice and this permission notice appear in all copies. --- --- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR --- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN --- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF --- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --- - -INSERT OR REPLACE INTO property( - key, - value -) -VALUES( - ?, - ? -)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-rpg/rpg/property.c Mon Oct 04 13:10:11 2021 +0200 @@ -0,0 +1,71 @@ +/* + * property.c -- manage game properties + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> + +#include <assets/sql/property-save.h> +#include <assets/sql/property-remove.h> +#include <assets/sql/property-load.h> + +#include "property.h" +#include "save.h" + +int +property_save(const struct property *p, struct save *s) +{ + assert(p); + assert(save_ok(s)); + + return save_exec(s, (const char *)assets_sql_property_save, "ss", p->key, p->value); +} + +int +property_load(struct property *p, struct save *s) +{ + assert(p); + assert(save_ok(s)); + + struct save_stmt stmt; + int ret; + + if (save_stmt_init(s, &stmt, (const char *)assets_sql_property_load, "s", p->key) < 0) + return -1; + + switch (save_stmt_next(&stmt, "s", p->value, sizeof (p->value))) { + case SAVE_STMT_DONE: + case SAVE_STMT_ERROR: + ret = -1; + break; + default: + ret = 0; + } + + save_stmt_finish(&stmt); + + return ret; +} + +int +property_remove(struct property *p, struct save *s) +{ + assert(p); + assert(save_ok(s)); + + return save_exec(s, (const char *)assets_sql_property_remove, "s", p->key); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-rpg/rpg/property.h Mon Oct 04 13:10:11 2021 +0200 @@ -0,0 +1,47 @@ +/* + * property.h -- manage game properties + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MOLKO_RPG_PROPERTY_H +#define MOLKO_RPG_PROPERTY_H + +#include <core/core.h> + +#define PROPERTY_KEY_MAX (64) +#define PROPERTY_VALUE_MAX (1024) + +struct save; + +struct property { + char key[PROPERTY_KEY_MAX + 1]; + char value[PROPERTY_VALUE_MAX + 1]; +}; + +CORE_BEGIN_DECLS + +int +property_save(const struct property *, struct save *); + +int +property_load(struct property *, struct save *); + +int +property_remove(struct property *, struct save *); + +CORE_END_DECLS + +#endif /* !MOLKO_RPG_PROPERTY_H */
--- a/src/libmlk-rpg/rpg/save.c Sun Oct 03 10:31:45 2021 +0200 +++ b/src/libmlk-rpg/rpg/save.c Mon Oct 04 13:10:11 2021 +0200 @@ -30,11 +30,9 @@ #include <core/util.h> #include <assets/sql/init.h> -#include <assets/sql/property-get.h> -#include <assets/sql/property-remove.h> -#include <assets/sql/property-set.h> #include "rpg_p.h" +#include "property.h" #include "save.h" #define SQL_BEGIN "BEGIN EXCLUSIVE TRANSACTION" @@ -67,7 +65,7 @@ { struct { time_t *date; - struct save_property prop; + struct property prop; } table[] = { { .date = &db->created, { .key = "molko.create-date" } }, { .date = &db->updated, { .key = "molko.update-date" } }, @@ -75,7 +73,7 @@ /* Ensure create and update dates are present. */ for (size_t i = 0; i < UTIL_SIZE(table); ++i) { - if (save_get_property(db, &table[i].prop) < 0) { + if (property_load(&table[i].prop, db) < 0) { sqlite3_close(db->handle); return errorf(_("database not initialized correctly")); } @@ -209,115 +207,6 @@ } int -save_set_property(struct save *db, const struct save_property *prop) -{ - assert(db); - assert(prop); - - sqlite3_stmt *stmt = NULL; - - if (exec(db, SQL_BEGIN) < 0) - return -1; - if (sqlite3_prepare(db->handle, (const char *)assets_sql_property_set, -1, &stmt, NULL) != SQLITE_OK) - goto sqlite3_err; - if (sqlite3_bind_text(stmt, 1, prop->key, -1, NULL) != SQLITE_OK || - sqlite3_bind_text(stmt, 2, prop->value, -1, NULL) != SQLITE_OK) - goto sqlite3_err; - if (sqlite3_step(stmt) != SQLITE_DONE) - goto sqlite3_err; - - sqlite3_finalize(stmt); - - return exec(db, SQL_COMMIT); - -sqlite3_err: - errorf("%s", sqlite3_errmsg(db->handle)); - - if (stmt) - sqlite3_finalize(stmt); - - exec(db, SQL_ROLLBACK); - - return -1; -} - -int -save_get_property(struct save *db, struct save_property *prop) -{ - assert(db); - assert(prop); - - sqlite3_stmt *stmt = NULL; - int ret = 0; - - if (sqlite3_prepare(db->handle, (const char *)assets_sql_property_get, - sizeof (assets_sql_property_get), &stmt, NULL) != SQLITE_OK) - goto sqlite3_err; - if (sqlite3_bind_text(stmt, 1, prop->key, -1, NULL) != SQLITE_OK) - goto sqlite3_err; - - switch (sqlite3_step(stmt)) { - case SQLITE_DONE: - /* Not found. */ - ret = errorf(_("property '%s' was not found"), prop->key); - break; - case SQLITE_ROW: - /* Found. */ - strlcpy(prop->value, (const char *)sqlite3_column_text(stmt, 0), - sizeof (prop->value)); - break; - default: - /* Error. */ - goto sqlite3_err; - } - - sqlite3_finalize(stmt); - - return ret; - -sqlite3_err: - errorf("%s", sqlite3_errmsg(db->handle)); - - if (stmt) - sqlite3_finalize(stmt); - - return -1; -} - -int -save_remove_property(struct save *db, const struct save_property *prop) -{ - assert(db); - assert(prop); - - sqlite3_stmt *stmt = NULL; - - if (exec(db, SQL_BEGIN) < 0) - return -1; - if (sqlite3_prepare(db->handle, (const char *)assets_sql_property_remove, - sizeof (assets_sql_property_remove), &stmt, NULL) != SQLITE_OK) - goto sqlite3_err; - if (sqlite3_bind_text(stmt, 1, prop->key, -1, NULL) != SQLITE_OK) - goto sqlite3_err; - if (sqlite3_step(stmt) != SQLITE_DONE) - goto sqlite3_err; - - sqlite3_finalize(stmt); - - return exec(db, SQL_COMMIT); - -sqlite3_err: - errorf("%s", sqlite3_errmsg(db->handle)); - - if (stmt) - sqlite3_finalize(stmt); - - exec(db, SQL_ROLLBACK); - - return -1; -} - -int save_exec(struct save *db, const char *sql, const char *args, ...) { assert(save_ok(db)); @@ -334,7 +223,7 @@ if (ret < 0) return -1; - ret = save_stmt_next(&stmt, NULL) == 0; + ret = save_stmt_next(&stmt, NULL); save_stmt_finish(&stmt); return ret; @@ -368,25 +257,25 @@ return ret; } -int +enum save_stmt_errno save_stmt_next(struct save_stmt *stmt, const char *args, ...) { assert(stmt); va_list ap; - int ret = -1; + enum save_stmt_errno ret = SAVE_STMT_ERROR; switch (sqlite3_step(stmt->handle)) { case SQLITE_ROW: va_start(ap, args); - - if (extract(stmt, args, ap)) - ret = 1; - + + if (extract(stmt, args, ap) == 0) + ret = SAVE_STMT_ROW; + va_end(ap); break; case SQLITE_DONE: - ret = 0; + ret = SAVE_STMT_DONE; break; default: break;
--- a/src/libmlk-rpg/rpg/save.h Sun Oct 03 10:31:45 2021 +0200 +++ b/src/libmlk-rpg/rpg/save.h Mon Oct 04 13:10:11 2021 +0200 @@ -23,9 +23,6 @@ #include <core/core.h> -#define SAVE_PROPERTY_KEY_MAX (64) -#define SAVE_PROPERTY_VALUE_MAX (1024) - struct save { time_t created; time_t updated; @@ -37,16 +34,17 @@ SAVE_MODE_WRITE }; -struct save_property { - char key[SAVE_PROPERTY_KEY_MAX + 1]; - char value[SAVE_PROPERTY_VALUE_MAX + 1]; -}; - struct save_stmt { struct save *parent; void *handle; }; +enum save_stmt_errno { + SAVE_STMT_DONE, + SAVE_STMT_ROW, + SAVE_STMT_ERROR +}; + CORE_BEGIN_DECLS int @@ -59,15 +57,6 @@ save_ok(const struct save *); int -save_set_property(struct save *, const struct save_property *); - -int -save_get_property(struct save *, struct save_property *); - -int -save_remove_property(struct save *, const struct save_property *); - -int save_exec(struct save *, const char *, const char *, ...); void @@ -77,7 +66,7 @@ int save_stmt_init(struct save *, struct save_stmt *, const char *, const char *, ...); -int +enum save_stmt_errno save_stmt_next(struct save_stmt *, const char *, ...); void
--- a/tests/test-save.c Sun Oct 03 10:31:45 2021 +0200 +++ b/tests/test-save.c Mon Oct 04 13:10:11 2021 +0200 @@ -21,6 +21,7 @@ #define GREATEST_USE_ABBREVS 0 #include <greatest.h> +#include <rpg/property.h> #include <rpg/save.h> static void @@ -89,22 +90,22 @@ properties_set(void) { struct save db; - struct save_property prop; + struct property prop; GREATEST_ASSERT(save_open_path(&db, "1.db", SAVE_MODE_WRITE) == 0); /* Insert a new property 'state'. */ - prop = (struct save_property){.key = "state", .value = "intro"}; - GREATEST_ASSERT(save_set_property(&db, &prop) == 0); - prop = (struct save_property){.key = "state"}; - GREATEST_ASSERT(save_get_property(&db, &prop) == 0); + prop = (struct property){.key = "state", .value = "intro"}; + GREATEST_ASSERT(property_save(&prop, &db) == 0); + prop = (struct property){.key = "state"}; + GREATEST_ASSERT(property_load(&prop, &db) == 0); GREATEST_ASSERT_STR_EQ(prop.value, "intro"); /* Now we replace the value. */ - prop = (struct save_property){.key = "state", .value = "map"}; - GREATEST_ASSERT(save_set_property(&db, &prop) == 0); - prop = (struct save_property){.key = "state"}; - GREATEST_ASSERT(save_get_property(&db, &prop) == 0); + prop = (struct property){.key = "state", .value = "map"}; + GREATEST_ASSERT(property_save(&prop, &db) == 0); + prop = (struct property){.key = "state"}; + GREATEST_ASSERT(property_load(&prop, &db) == 0); GREATEST_ASSERT_STR_EQ(prop.value, "map"); save_finish(&db); @@ -116,10 +117,10 @@ properties_notfound(void) { struct save db; - struct save_property prop = {.key = "state"}; + struct property prop = {.key = "state"}; GREATEST_ASSERT(save_open_path(&db, "1.db", SAVE_MODE_WRITE) == 0); - GREATEST_ASSERT(save_get_property(&db, &prop) < 0); + GREATEST_ASSERT(property_load(&prop, &db) < 0); GREATEST_ASSERT_STR_EQ(prop.value, ""); GREATEST_PASS(); @@ -129,17 +130,17 @@ properties_remove(void) { struct save db; - struct save_property prop; + struct property prop; GREATEST_ASSERT(save_open_path(&db, "1.db", SAVE_MODE_WRITE) == 0); /* Insert a new property 'initialized'. */ - prop = (struct save_property){.key = "state", .value = "intro"}; - GREATEST_ASSERT(save_set_property(&db, &prop) == 0); - prop = (struct save_property){.key = "state"}; - GREATEST_ASSERT(save_remove_property(&db, &prop) == 0); - prop = (struct save_property){.key = "state"}; - GREATEST_ASSERT(save_get_property(&db, &prop) < 0); + prop = (struct property){.key = "state", .value = "intro"}; + GREATEST_ASSERT(property_save(&prop, &db) == 0); + prop = (struct property){.key = "state"}; + GREATEST_ASSERT(property_remove(&prop, &db) == 0); + prop = (struct property){.key = "state"}; + GREATEST_ASSERT(property_load(&prop, &db) < 0); GREATEST_ASSERT_STR_EQ(prop.value, ""); GREATEST_PASS();