Mercurial > molko
diff libcore/core/save.c @ 121:789b23e01f52
misc: reorganize hierarchy, closes #2490
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 05 Oct 2020 13:25:06 +0200 |
parents | src/core/save.c@a6c2067709ce |
children | aab824406d3d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcore/core/save.c Mon Oct 05 13:25:06 2020 +0200 @@ -0,0 +1,214 @@ +/* + * save.c -- save functions + * + * Copyright (c) 2020 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 <stdio.h> +#include <string.h> + +#include <sqlite3.h> + +#include "error.h" +#include "save.h" +#include "sys.h" + +static sqlite3 *db; + +static const char *sinit = + "BEGIN EXCLUSIVE TRANSACTION;" + "" + "CREATE TABLE IF NOT EXISTS property(" + " id INTEGER PRIMARY KEY AUTOINCREMENT," + " key TEXT NOT NULL UNIQUE," + " value TEXT NOT NULL" + ");" + "" + "COMMIT" +; + +static const char *sbegin = + "BEGIN EXCLUSIVE TRANSACTION" +; + +static const char *scommit = + "COMMIT" +; + +static const char *srollback = + "ROLLBACK" +; + +static const char *sset_property = + "INSERT OR REPLACE INTO property(" + " key," + " value" + ")" + "VALUES(" + " ?," + " ?" + ");" +; + +static const char *sget_property = + "SELECT value" + " FROM property" + " WHERE key = ?" +; + +static const char *sremove_property = + "DELETE" + " FROM property" + " WHERE key = ?" +; + +static bool +exec(const char *sql) +{ + if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) + return error_printf("%s", sqlite3_errmsg(db)); + + return true; +} + +bool +save_open(unsigned int idx) +{ + return save_open_path(sys_savepath(idx)); +} + +bool +save_open_path(const char *path) +{ + assert(path); + + if (sqlite3_open(path, &db) != SQLITE_OK) + return error_printf("database open error: %s", sqlite3_errmsg(db)); + if (sqlite3_exec(db, sinit, NULL, NULL, NULL) != SQLITE_OK) + return error_printf("database init error: %s", sqlite3_errmsg(db)); + + return true; +} + +bool +save_set_property(const char *key, const char *value) +{ + assert(key); + assert(value && strlen(value) <= SAVE_PROPERTY_VALUE_MAX); + + sqlite3_stmt *stmt = NULL; + + if (!exec(sbegin)) + return false; + if (sqlite3_prepare(db, sset_property, -1, &stmt, NULL) != SQLITE_OK) + goto sqlite3_err; + if (sqlite3_bind_text(stmt, 1, key, -1, NULL) != SQLITE_OK || + sqlite3_bind_text(stmt, 2, value, -1, NULL) != SQLITE_OK) + goto sqlite3_err; + if (sqlite3_step(stmt) != SQLITE_DONE) + goto sqlite3_err; + + sqlite3_finalize(stmt); + + return exec(scommit); + +sqlite3_err: + if (stmt) { + sqlite3_finalize(stmt); + exec(srollback); + } + + return error_printf("%s", sqlite3_errmsg(db)); +} + +const char * +save_get_property(const char *key) +{ + assert(key); + + static char value[SAVE_PROPERTY_VALUE_MAX + 1]; + const char *ret = value; + sqlite3_stmt *stmt = NULL; + + memset(value, 0, sizeof (value)); + + if (sqlite3_prepare(db, sget_property, -1, &stmt, NULL) != SQLITE_OK) + goto sqlite3_err; + if (sqlite3_bind_text(stmt, 1, key, -1, NULL) != SQLITE_OK) + goto sqlite3_err; + + switch (sqlite3_step(stmt)) { + case SQLITE_DONE: + /* Not found. */ + ret = NULL; + break; + case SQLITE_ROW: + /* Found. */ + snprintf(value, sizeof (value), "%s", sqlite3_column_text(stmt, 0)); + break; + default: + /* Error. */ + goto sqlite3_err; + } + + sqlite3_finalize(stmt); + + return ret; + +sqlite3_err: + if (stmt) + sqlite3_finalize(stmt); + + error_printf("%s", sqlite3_errmsg(db)); + + return NULL; +} + +bool +save_remove_property(const char *key) +{ + assert(key); + + sqlite3_stmt *stmt = NULL; + + if (!exec(sbegin)) + return false; + if (sqlite3_prepare(db, sremove_property, -1, &stmt, NULL) != SQLITE_OK) + goto sqlite3_err; + if (sqlite3_bind_text(stmt, 1, key, -1, NULL) != SQLITE_OK) + goto sqlite3_err; + if (sqlite3_step(stmt) != SQLITE_DONE) + goto sqlite3_err; + + sqlite3_finalize(stmt); + + return exec(scommit); + +sqlite3_err: + if (stmt) + sqlite3_finalize(stmt); + + error_printf("%s", sqlite3_errmsg(db)); + + return false; +} + +void +save_finish(void) +{ + if (db) + sqlite3_close(db); +}