diff options
Diffstat (limited to '')
-rw-r--r-- | src/sticker/Match.hxx | 49 | ||||
-rw-r--r-- | src/sticker/SongSticker.cxx | 43 | ||||
-rw-r--r-- | src/sticker/SongSticker.hxx | 24 | ||||
-rw-r--r-- | src/sticker/StickerDatabase.cxx | 398 | ||||
-rw-r--r-- | src/sticker/StickerDatabase.hxx | 38 | ||||
-rw-r--r-- | src/sticker/StickerPrint.cxx | 4 | ||||
-rw-r--r-- | src/sticker/StickerPrint.hxx | 6 |
7 files changed, 237 insertions, 325 deletions
diff --git a/src/sticker/Match.hxx b/src/sticker/Match.hxx new file mode 100644 index 000000000..4ac2ac383 --- /dev/null +++ b/src/sticker/Match.hxx @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2003-2015 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_STICKER_MATCH_HXX +#define MPD_STICKER_MATCH_HXX + +enum class StickerOperator { + /** + * Matches if a sticker with the specified name exists. The + * "value" parameter is ignored (must be nullptr). + */ + EXISTS, + + /** + * Matches if a sticker with the specified name and value + * exists. + */ + EQUALS, + + /** + * Matches if a sticker with the specified name exists with a + * value smaller than the specified one. + */ + LESS_THAN, + + /** + * Matches if a sticker with the specified name exists with a + * value bigger than the specified one. + */ + GREATER_THAN, +}; + +#endif diff --git a/src/sticker/SongSticker.cxx b/src/sticker/SongSticker.cxx index b6f46f167..b4ca6a398 100644 --- a/src/sticker/SongSticker.cxx +++ b/src/sticker/SongSticker.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,46 +23,48 @@ #include "db/LightSong.hxx" #include "db/Interface.hxx" #include "util/Error.hxx" - -#include <glib.h> +#include "util/Alloc.hxx" #include <assert.h> #include <string.h> +#include <stdlib.h> std::string -sticker_song_get_value(const LightSong &song, const char *name) +sticker_song_get_value(const LightSong &song, const char *name, Error &error) { const auto uri = song.GetURI(); - return sticker_load_value("song", uri.c_str(), name); + return sticker_load_value("song", uri.c_str(), name, error); } bool sticker_song_set_value(const LightSong &song, - const char *name, const char *value) + const char *name, const char *value, + Error &error) { const auto uri = song.GetURI(); - return sticker_store_value("song", uri.c_str(), name, value); + return sticker_store_value("song", uri.c_str(), name, value, error); } bool -sticker_song_delete(const LightSong &song) +sticker_song_delete(const LightSong &song, Error &error) { const auto uri = song.GetURI(); - return sticker_delete("song", uri.c_str()); + return sticker_delete("song", uri.c_str(), error); } bool -sticker_song_delete_value(const LightSong &song, const char *name) +sticker_song_delete_value(const LightSong &song, const char *name, + Error &error) { const auto uri = song.GetURI(); - return sticker_delete_value("song", uri.c_str(), name); + return sticker_delete_value("song", uri.c_str(), name, error); } -struct sticker * -sticker_song_get(const LightSong &song) +Sticker * +sticker_song_get(const LightSong &song, Error &error) { const auto uri = song.GetURI(); - return sticker_load("song", uri.c_str()); + return sticker_load("song", uri.c_str(), error); } struct sticker_song_find_data { @@ -95,9 +97,11 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data) bool sticker_song_find(const Database &db, const char *base_uri, const char *name, + StickerOperator op, const char *value, void (*func)(const LightSong &song, const char *value, void *user_data), - void *user_data) + void *user_data, + Error &error) { struct sticker_song_find_data data; data.db = &db; @@ -109,16 +113,17 @@ sticker_song_find(const Database &db, const char *base_uri, const char *name, if (*data.base_uri != 0) /* append slash to base_uri */ data.base_uri = allocated = - g_strconcat(data.base_uri, "/", nullptr); + xstrcatdup(data.base_uri, "/"); else /* searching in root directory - no trailing slash */ allocated = nullptr; data.base_uri_length = strlen(data.base_uri); - bool success = sticker_find("song", data.base_uri, name, - sticker_song_find_cb, &data); - g_free(allocated); + bool success = sticker_find("song", data.base_uri, name, op, value, + sticker_song_find_cb, &data, + error); + free(allocated); return success; } diff --git a/src/sticker/SongSticker.hxx b/src/sticker/SongSticker.hxx index 5956cd6f9..3eaa1d776 100644 --- a/src/sticker/SongSticker.hxx +++ b/src/sticker/SongSticker.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,13 +20,15 @@ #ifndef MPD_SONG_STICKER_HXX #define MPD_SONG_STICKER_HXX +#include "Match.hxx" #include "Compiler.h" #include <string> struct LightSong; -struct sticker; +struct Sticker; class Database; +class Error; /** * Returns one value from a song's sticker record. The caller must @@ -34,7 +36,7 @@ class Database; */ gcc_pure std::string -sticker_song_get_value(const LightSong &song, const char *name); +sticker_song_get_value(const LightSong &song, const char *name, Error &error); /** * Sets a sticker value in the specified song. Overwrites existing @@ -42,20 +44,22 @@ sticker_song_get_value(const LightSong &song, const char *name); */ bool sticker_song_set_value(const LightSong &song, - const char *name, const char *value); + const char *name, const char *value, + Error &error); /** * Deletes a sticker from the database. All values are deleted. */ bool -sticker_song_delete(const LightSong &song); +sticker_song_delete(const LightSong &song, Error &error); /** * Deletes a sticker value. Does nothing if the sticker did not * exist. */ bool -sticker_song_delete_value(const LightSong &song, const char *name); +sticker_song_delete_value(const LightSong &song, const char *name, + Error &error); /** * Loads the sticker for the specified song. @@ -63,8 +67,8 @@ sticker_song_delete_value(const LightSong &song, const char *name); * @param song the song object * @return a sticker object, or NULL on error or if there is no sticker */ -sticker * -sticker_song_get(const LightSong &song); +Sticker * +sticker_song_get(const LightSong &song, Error &error); /** * Finds stickers with the specified name below the specified @@ -79,8 +83,10 @@ sticker_song_get(const LightSong &song); */ bool sticker_song_find(const Database &db, const char *base_uri, const char *name, + StickerOperator op, const char *value, void (*func)(const LightSong &song, const char *value, void *user_data), - void *user_data); + void *user_data, + Error &error); #endif diff --git a/src/sticker/StickerDatabase.cxx b/src/sticker/StickerDatabase.cxx index 93eaa900d..02eed362e 100644 --- a/src/sticker/StickerDatabase.cxx +++ b/src/sticker/StickerDatabase.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,24 +19,19 @@ #include "config.h" #include "StickerDatabase.hxx" +#include "lib/sqlite/Domain.hxx" +#include "lib/sqlite/Util.hxx" #include "fs/Path.hxx" #include "Idle.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" #include "util/Macros.hxx" -#include "Log.hxx" #include <string> #include <map> -#include <sqlite3.h> #include <assert.h> -#if SQLITE_VERSION_NUMBER < 3003009 -#define sqlite3_prepare_v2 sqlite3_prepare -#endif - -struct sticker { +struct Sticker { std::map<std::string, std::string> table; }; @@ -48,6 +43,9 @@ enum sticker_sql { STICKER_SQL_DELETE, STICKER_SQL_DELETE_VALUE, STICKER_SQL_FIND, + STICKER_SQL_FIND_VALUE, + STICKER_SQL_FIND_LT, + STICKER_SQL_FIND_GT, }; static const char *const sticker_sql[] = { @@ -65,6 +63,15 @@ static const char *const sticker_sql[] = { "DELETE FROM sticker WHERE type=? AND uri=? AND name=?", //[STICKER_SQL_FIND] = "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=?", + + //[STICKER_SQL_FIND_VALUE] = + "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value=?", + + //[STICKER_SQL_FIND_LT] = + "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value<?", + + //[STICKER_SQL_FIND_GT] = + "SELECT uri,value FROM sticker WHERE type=? AND uri LIKE (? || '%') AND name=? AND value>?", }; static const char sticker_sql_create[] = @@ -81,23 +88,13 @@ static const char sticker_sql_create[] = static sqlite3 *sticker_db; static sqlite3_stmt *sticker_stmt[ARRAY_SIZE(sticker_sql)]; -static constexpr Domain sticker_domain("sticker"); - -static void -LogError(sqlite3 *db, const char *msg) -{ - FormatError(sticker_domain, "%s: %s", msg, sqlite3_errmsg(db)); -} - static sqlite3_stmt * sticker_prepare(const char *sql, Error &error) { - int ret; sqlite3_stmt *stmt; - - ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, nullptr); + int ret = sqlite3_prepare_v2(sticker_db, sql, -1, &stmt, nullptr); if (ret != SQLITE_OK) { - error.Format(sticker_domain, ret, + error.Format(sqlite_domain, ret, "sqlite3_prepare_v2() failed: %s", sqlite3_errmsg(sticker_db)); return nullptr; @@ -118,9 +115,9 @@ sticker_global_init(Path path, Error &error) ret = sqlite3_open(path.c_str(), &sticker_db); if (ret != SQLITE_OK) { const std::string utf8 = path.ToUTF8(); - error.Format(sticker_domain, ret, - "Failed to open sqlite database '%s': %s", - utf8.c_str(), sqlite3_errmsg(sticker_db)); + error.Format(sqlite_domain, ret, + "Failed to open sqlite database '%s': %s", + utf8.c_str(), sqlite3_errmsg(sticker_db)); return false; } @@ -129,7 +126,7 @@ sticker_global_init(Path path, Error &error) ret = sqlite3_exec(sticker_db, sticker_sql_create, nullptr, nullptr, nullptr); if (ret != SQLITE_OK) { - error.Format(sticker_domain, ret, + error.Format(sqlite_domain, ret, "Failed to create sticker table: %s", sqlite3_errmsg(sticker_db)); return false; @@ -149,7 +146,7 @@ sticker_global_init(Path path, Error &error) } void -sticker_global_finish(void) +sticker_global_finish() { if (sticker_db == nullptr) /* not configured */ @@ -165,16 +162,16 @@ sticker_global_finish(void) } bool -sticker_enabled(void) +sticker_enabled() { return sticker_db != nullptr; } std::string -sticker_load_value(const char *type, const char *uri, const char *name) +sticker_load_value(const char *type, const char *uri, const char *name, + Error &error) { sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_GET]; - int ret; assert(sticker_enabled()); assert(type != nullptr); @@ -184,40 +181,12 @@ sticker_load_value(const char *type, const char *uri, const char *name) if (*name == 0) return std::string(); - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return std::string(); - } - - ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return std::string(); - } - - ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + if (!BindAll(error, stmt, type, uri, name)) return std::string(); - } - - do { - ret = sqlite3_step(stmt); - } while (ret == SQLITE_BUSY); std::string value; - if (ret == SQLITE_ROW) { - /* record found */ + if (ExecuteRow(stmt, error)) value = (const char*)sqlite3_column_text(stmt, 0); - } else if (ret == SQLITE_DONE) { - /* no record found */ - } else { - /* error */ - LogError(sticker_db, "sqlite3_step() failed"); - } sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); @@ -227,63 +196,36 @@ sticker_load_value(const char *type, const char *uri, const char *name) static bool sticker_list_values(std::map<std::string, std::string> &table, - const char *type, const char *uri) + const char *type, const char *uri, + Error &error) { sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_LIST]; - int ret; assert(type != nullptr); assert(uri != nullptr); assert(sticker_enabled()); - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + if (!BindAll(error, stmt, type, uri)) return false; - } - - ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - do { - ret = sqlite3_step(stmt); - switch (ret) { - const char *name, *value; - - case SQLITE_ROW: - name = (const char*)sqlite3_column_text(stmt, 0); - value = (const char*)sqlite3_column_text(stmt, 1); + const bool success = ExecuteForEach(stmt, error, [stmt, &table](){ + const char *name = (const char *)sqlite3_column_text(stmt, 0); + const char *value = (const char *)sqlite3_column_text(stmt, 1); table.insert(std::make_pair(name, value)); - break; - case SQLITE_DONE: - break; - case SQLITE_BUSY: - /* no op */ - break; - default: - LogError(sticker_db, "sqlite3_step() failed"); - return false; - } - } while (ret != SQLITE_DONE); + }); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); - return true; + return success; } static bool sticker_update_value(const char *type, const char *uri, - const char *name, const char *value) + const char *name, const char *value, + Error &error) { sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_UPDATE]; - int ret; assert(type != nullptr); assert(uri != nullptr); @@ -293,56 +235,25 @@ sticker_update_value(const char *type, const char *uri, assert(sticker_enabled()); - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, value, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 2, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + if (!BindAll(error, stmt, value, type, uri, name)) return false; - } - ret = sqlite3_bind_text(stmt, 3, uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 4, name, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - do { - ret = sqlite3_step(stmt); - } while (ret == SQLITE_BUSY); - - if (ret != SQLITE_DONE) { - LogError(sticker_db, "sqlite3_step() failed"); - return false; - } - - ret = sqlite3_changes(sticker_db); + bool modified = ExecuteModified(stmt, error); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); - idle_add(IDLE_STICKER); - return ret > 0; + if (modified) + idle_add(IDLE_STICKER); + return modified; } static bool sticker_insert_value(const char *type, const char *uri, - const char *name, const char *value) + const char *name, const char *value, + Error &error) { sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_INSERT]; - int ret; assert(type != nullptr); assert(uri != nullptr); @@ -352,52 +263,23 @@ sticker_insert_value(const char *type, const char *uri, assert(sticker_enabled()); - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 4, value, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + if (!BindAll(error, stmt, type, uri, name, value)) return false; - } - do { - ret = sqlite3_step(stmt); - } while (ret == SQLITE_BUSY); - - if (ret != SQLITE_DONE) { - LogError(sticker_db, "sqlite3_step() failed"); - return false; - } + bool success = ExecuteCommand(stmt, error); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); - - idle_add(IDLE_STICKER); - return true; + if (success) + idle_add(IDLE_STICKER); + return success; } bool sticker_store_value(const char *type, const char *uri, - const char *name, const char *value) + const char *name, const char *value, + Error &error) { assert(sticker_enabled()); assert(type != nullptr); @@ -408,106 +290,63 @@ sticker_store_value(const char *type, const char *uri, if (*name == 0) return false; - return sticker_update_value(type, uri, name, value) || - sticker_insert_value(type, uri, name, value); + return sticker_update_value(type, uri, name, value, error) || + sticker_insert_value(type, uri, name, value, error); } bool -sticker_delete(const char *type, const char *uri) +sticker_delete(const char *type, const char *uri, Error &error) { sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_DELETE]; - int ret; assert(sticker_enabled()); assert(type != nullptr); assert(uri != nullptr); - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + if (!BindAll(error, stmt, type, uri)) return false; - } - do { - ret = sqlite3_step(stmt); - } while (ret == SQLITE_BUSY); - - if (ret != SQLITE_DONE) { - LogError(sticker_db, "sqlite3_step() failed"); - return false; - } + bool modified = ExecuteModified(stmt, error); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); - idle_add(IDLE_STICKER); - return true; + if (modified) + idle_add(IDLE_STICKER); + return modified; } bool -sticker_delete_value(const char *type, const char *uri, const char *name) +sticker_delete_value(const char *type, const char *uri, const char *name, + Error &error) { sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_DELETE_VALUE]; - int ret; assert(sticker_enabled()); assert(type != nullptr); assert(uri != nullptr); - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - - ret = sqlite3_bind_text(stmt, 2, uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + if (!BindAll(error, stmt, type, uri, name)) return false; - } - - ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } - do { - ret = sqlite3_step(stmt); - } while (ret == SQLITE_BUSY); - - if (ret != SQLITE_DONE) { - LogError(sticker_db, "sqlite3_step() failed"); - return false; - } - - ret = sqlite3_changes(sticker_db); + bool modified = ExecuteModified(stmt, error); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); - idle_add(IDLE_STICKER); - return ret > 0; + if (modified) + idle_add(IDLE_STICKER); + return modified; } void -sticker_free(struct sticker *sticker) +sticker_free(Sticker *sticker) { delete sticker; } const char * -sticker_get_value(const struct sticker &sticker, const char *name) +sticker_get_value(const Sticker &sticker, const char *name) { auto i = sticker.table.find(name); if (i == sticker.table.end()) @@ -517,7 +356,7 @@ sticker_get_value(const struct sticker &sticker, const char *name) } void -sticker_foreach(const sticker &sticker, +sticker_foreach(const Sticker &sticker, void (*func)(const char *name, const char *value, void *user_data), void *user_data) @@ -526,79 +365,82 @@ sticker_foreach(const sticker &sticker, func(i.first.c_str(), i.second.c_str(), user_data); } -struct sticker * -sticker_load(const char *type, const char *uri) +Sticker * +sticker_load(const char *type, const char *uri, Error &error) { - sticker s; + Sticker s; - if (!sticker_list_values(s.table, type, uri)) + if (!sticker_list_values(s.table, type, uri, error)) return nullptr; if (s.table.empty()) /* don't return empty sticker objects */ return nullptr; - return new sticker(std::move(s)); + return new Sticker(std::move(s)); } -bool -sticker_find(const char *type, const char *base_uri, const char *name, - void (*func)(const char *uri, const char *value, - void *user_data), - void *user_data) +static sqlite3_stmt * +BindFind(const char *type, const char *base_uri, const char *name, + StickerOperator op, const char *value, + Error &error) { - sqlite3_stmt *const stmt = sticker_stmt[STICKER_SQL_FIND]; - int ret; - assert(type != nullptr); assert(name != nullptr); - assert(func != nullptr); - assert(sticker_enabled()); - - sqlite3_reset(stmt); - - ret = sqlite3_bind_text(stmt, 1, type, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; - } if (base_uri == nullptr) base_uri = ""; - ret = sqlite3_bind_text(stmt, 2, base_uri, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); - return false; + switch (op) { + case StickerOperator::EXISTS: + return BindAllOrNull(error, sticker_stmt[STICKER_SQL_FIND], + type, base_uri, name); + + case StickerOperator::EQUALS: + return BindAllOrNull(error, + sticker_stmt[STICKER_SQL_FIND_VALUE], + type, base_uri, name, value); + + case StickerOperator::LESS_THAN: + return BindAllOrNull(error, + sticker_stmt[STICKER_SQL_FIND_LT], + type, base_uri, name, value); + + case StickerOperator::GREATER_THAN: + return BindAllOrNull(error, + sticker_stmt[STICKER_SQL_FIND_GT], + type, base_uri, name, value); } - ret = sqlite3_bind_text(stmt, 3, name, -1, nullptr); - if (ret != SQLITE_OK) { - LogError(sticker_db, "sqlite3_bind_text() failed"); + assert(false); + gcc_unreachable(); +} + +bool +sticker_find(const char *type, const char *base_uri, const char *name, + StickerOperator op, const char *value, + void (*func)(const char *uri, const char *value, + void *user_data), + void *user_data, + Error &error) +{ + assert(func != nullptr); + assert(sticker_enabled()); + + sqlite3_stmt *const stmt = BindFind(type, base_uri, name, op, value, + error); + if (stmt == nullptr) return false; - } - do { - ret = sqlite3_step(stmt); - switch (ret) { - case SQLITE_ROW: + const bool success = ExecuteForEach(stmt, error, + [stmt, func, user_data](){ func((const char*)sqlite3_column_text(stmt, 0), (const char*)sqlite3_column_text(stmt, 1), user_data); - break; - case SQLITE_DONE: - break; - case SQLITE_BUSY: - /* no op */ - break; - default: - LogError(sticker_db, "sqlite3_step() failed"); - return false; - } - } while (ret != SQLITE_DONE); + }); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); - return true; + return success; } diff --git a/src/sticker/StickerDatabase.hxx b/src/sticker/StickerDatabase.hxx index 8993489c4..d9a5ecf11 100644 --- a/src/sticker/StickerDatabase.hxx +++ b/src/sticker/StickerDatabase.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -42,13 +42,14 @@ #ifndef MPD_STICKER_DATABASE_HXX #define MPD_STICKER_DATABASE_HXX +#include "Match.hxx" #include "Compiler.h" #include <string> class Error; class Path; -struct sticker; +struct Sticker; /** * Opens the sticker database. @@ -62,21 +63,22 @@ sticker_global_init(Path path, Error &error); * Close the sticker database. */ void -sticker_global_finish(void); +sticker_global_finish(); /** * Returns true if the sticker database is configured and available. */ gcc_const bool -sticker_enabled(void); +sticker_enabled(); /** * Returns one value from an object's sticker record. Returns an * empty string if the value doesn't exist. */ std::string -sticker_load_value(const char *type, const char *uri, const char *name); +sticker_load_value(const char *type, const char *uri, const char *name, + Error &error); /** * Sets a sticker value in the specified object. Overwrites existing @@ -84,21 +86,24 @@ sticker_load_value(const char *type, const char *uri, const char *name); */ bool sticker_store_value(const char *type, const char *uri, - const char *name, const char *value); + const char *name, const char *value, + Error &error); /** * Deletes a sticker from the database. All sticker values of the * specified object are deleted. */ bool -sticker_delete(const char *type, const char *uri); +sticker_delete(const char *type, const char *uri, + Error &error); /** * Deletes a sticker value. Fails if no sticker with this name * exists. */ bool -sticker_delete_value(const char *type, const char *uri, const char *name); +sticker_delete_value(const char *type, const char *uri, const char *name, + Error &error); /** * Frees resources held by the sticker object. @@ -106,7 +111,7 @@ sticker_delete_value(const char *type, const char *uri, const char *name); * @param sticker the sticker object to be freed */ void -sticker_free(sticker *sticker); +sticker_free(Sticker *sticker); /** * Determines a single value in a sticker. @@ -117,7 +122,7 @@ sticker_free(sticker *sticker); */ gcc_pure const char * -sticker_get_value(const sticker &sticker, const char *name); +sticker_get_value(const Sticker &sticker, const char *name); /** * Iterates over all sticker items in a sticker. @@ -127,7 +132,7 @@ sticker_get_value(const sticker &sticker, const char *name); * @param user_data an opaque pointer for the callback function */ void -sticker_foreach(const sticker &sticker, +sticker_foreach(const Sticker &sticker, void (*func)(const char *name, const char *value, void *user_data), void *user_data); @@ -139,8 +144,9 @@ sticker_foreach(const sticker &sticker, * @param uri the URI of the resource, e.g. the song path * @return a sticker object, or nullptr on error or if there is no sticker */ -sticker * -sticker_load(const char *type, const char *uri); +Sticker * +sticker_load(const char *type, const char *uri, + Error &error); /** * Finds stickers with the specified name below the specified URI. @@ -149,13 +155,17 @@ sticker_load(const char *type, const char *uri); * @param base_uri the URI prefix of the resources, or nullptr if all * resources should be searched * @param name the name of the sticker + * @param op the comparison operator + * @param value the operand * @return true on success (even if no sticker was found), false on * failure */ bool sticker_find(const char *type, const char *base_uri, const char *name, + StickerOperator op, const char *value, void (*func)(const char *uri, const char *value, void *user_data), - void *user_data); + void *user_data, + Error &error); #endif diff --git a/src/sticker/StickerPrint.cxx b/src/sticker/StickerPrint.cxx index a952ff203..1682abf77 100644 --- a/src/sticker/StickerPrint.cxx +++ b/src/sticker/StickerPrint.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -38,7 +38,7 @@ print_sticker_cb(const char *name, const char *value, void *data) } void -sticker_print(Client &client, const sticker &sticker) +sticker_print(Client &client, const Sticker &sticker) { sticker_foreach(sticker, print_sticker_cb, &client); } diff --git a/src/sticker/StickerPrint.hxx b/src/sticker/StickerPrint.hxx index 39f3dc09e..53aaca8df 100644 --- a/src/sticker/StickerPrint.hxx +++ b/src/sticker/StickerPrint.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@ #ifndef MPD_STICKER_PRINT_HXX #define MPD_STICKER_PRINT_HXX -struct sticker; +struct Sticker; class Client; /** @@ -33,6 +33,6 @@ sticker_print_value(Client &client, const char *name, const char *value); * Sends all sticker values to the client. */ void -sticker_print(Client &client, const sticker &sticker); +sticker_print(Client &client, const Sticker &sticker); #endif |