core/database: Add operations vector

I intend to replace C++ inheritance with this struct of function
pointers.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-11-03 10:39:06 -05:00
parent 847e4c1925
commit ab1572ed34
20 changed files with 98 additions and 17 deletions

View File

@ -42,11 +42,14 @@ void index_entry :: read(file &file)
}
static const struct db_ops index_ops = {
};
void index_init(database<index_entry> *index, const gchar *filepath,
bool autosave)
{
db_init(index, filepath, autosave);
db_init(index, filepath, autosave, &index_ops);
}
index_entry *index_insert(database<index_entry> *index, const gchar *key,
@ -77,3 +80,7 @@ bool index_has(database<index_entry> *index, const gchar *key, unsigned int valu
return false;
return set_has(&it->ie_set, value);
}
#ifdef CONFIG_TESTING
const struct db_ops *test_index_ops() { return &index_ops; }
#endif /* CONFIG_TESTING */

View File

@ -59,9 +59,13 @@ void album :: write(file &file)
}
static const struct db_ops album_ops = {
};
void album_db_init()
{
db_init(&album_db, "album.db", true);
db_init(&album_db, "album.db", true, &album_ops);
db_load(&album_db);
}
@ -84,3 +88,7 @@ int album_compare(struct album *lhs, struct album *rhs)
{
return string_compare(lhs->al_lower.c_str(), rhs->al_lower.c_str());
}
#ifdef CONFIG_TESTING
const struct db_ops *test_album_ops() { return &album_ops; }
#endif /* CONFIG_TESTING */

View File

@ -45,9 +45,13 @@ void artist :: write(file &file)
}
static const struct db_ops artist_ops = {
};
void artist_db_init()
{
db_init(&artist_db, "artist.db", true);
db_init(&artist_db, "artist.db", true, &artist_ops);
db_load(&artist_db);
}
@ -70,3 +74,7 @@ int artist_compare(struct artist *lhs, struct artist *rhs)
{
return string_compare(lhs->ar_lower.c_str(), rhs->ar_lower.c_str());
}
#ifdef CONFIG_TESTING
const struct db_ops *test_artist_ops() { return &artist_ops; }
#endif /* CONFIG_TESTING */

View File

@ -44,9 +44,13 @@ void genre :: write(file &file)
}
static const struct db_ops genre_ops = {
};
void genre_db_init()
{
db_init(&genre_db, "genre.db", true);
db_init(&genre_db, "genre.db", true, &genre_ops);
db_load(&genre_db);
}
@ -69,3 +73,7 @@ int genre_compare(struct genre *lhs, struct genre *rhs)
{
return string_compare(lhs->ge_lower.c_str(), rhs->ge_lower.c_str());
}
#ifdef CONFIG_TESTING
const struct db_ops *test_genre_ops() { return &genre_ops; }
#endif /* CONFIG_TESTING */

View File

@ -41,9 +41,13 @@ void library :: write(file &file)
}
static const struct db_ops library_ops = {
};
void library_db_init()
{
db_init(&library_db, "library.db", true);
db_init(&library_db, "library.db", true, &library_ops);
db_load(&library_db);
}
@ -83,3 +87,7 @@ std::string library_file(struct library *library, const std::string &path)
{
return library->li_path + "/" + path;
}
#ifdef CONFIG_TESTING
const struct db_ops *test_library_ops() { return &library_ops; }
#endif /* CONFIG_TESTING */

View File

@ -135,9 +135,13 @@ void track :: write(file &file)
}
static const struct db_ops track_ops = {
};
void track_db_init()
{
db_init(&track_db, "track.db", false);
db_init(&track_db, "track.db", false, &track_ops);
db_load(&track_db);
}
@ -217,3 +221,7 @@ const std::string track_last_play(struct track *track)
}
return res;
}
#ifdef CONFIG_TESTING
const struct db_ops *test_track_ops() { return &track_ops; }
#endif /* CONFIG_TESTING */

View File

@ -51,6 +51,10 @@ struct db_entry {
};
struct db_ops {
};
/**
* Databases are a generic store for information used by Ocarina. Users
* need to inherit from a DatabaseEntry class to properly use a Database.
@ -75,6 +79,7 @@ struct database {
bool db_autosave; /* True if the database saves when changed. */
struct file db_file; /* The database's associated file object. */
const struct db_ops *db_ops; /* The database's operations vector. */
std::vector<T *> db_entries;
std::map<const std::string, unsigned int> db_keys;
};
@ -85,7 +90,7 @@ struct database {
* and autosave as a hint for if this database should be automatically saved.
*/
template <class T>
void db_init(struct database<T> *, const char *, bool);
void db_init(struct database<T> *, const char *, bool, const struct db_ops *);
/* Called to prevent memory leaks by freeing all remaining database entries. */
template <class T>

View File

@ -8,8 +8,10 @@
#define OCARINA_DATABASE_HPP
template <class T>
void db_init(struct database<T> *db, const char *filepath, bool autosave)
void db_init(struct database<T> *db, const char *filepath, bool autosave,
const struct db_ops *ops)
{
db->db_ops = ops;
db->db_size = 0;
db->db_autosave = autosave;
file_init(&db->db_file, filepath, 0);

View File

@ -66,4 +66,7 @@ void index_remove(database<index_entry> *, const gchar *, unsigned int);
/* Called to check if the index has the specified (key, value) pair. */
bool index_has(database<index_entry> *, const gchar *, unsigned int);
#ifdef CONFIG_TESTING
const struct db_ops *test_index_ops();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_DATABASE_H */

View File

@ -69,4 +69,7 @@ struct album *album_get(const unsigned int);
/* Called to compare two album tags. */
int album_compare(struct album *, struct album *);
#ifdef CONFIG_TESTING
const struct db_ops *test_album_ops();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_TAGS_ALBUM_H */

View File

@ -44,4 +44,7 @@ struct artist *artist_get(const unsigned int);
/* Called to compare two artist tags. */
int artist_compare(struct artist *, struct artist *);
#ifdef CONFIG_TESTING
const struct db_ops *test_artist_ops();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_TAGS_ARTIST_H */

View File

@ -45,4 +45,7 @@ struct genre *genre_get(const unsigned int);
/* Called to compare two genre tags. */
int genre_compare(struct genre *, struct genre *);
#ifdef CONFIG_TESTING
const struct db_ops *test_genre_ops();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_TAGS_GENRE_H */

View File

@ -78,4 +78,7 @@ void library_set_enabled(struct library *, bool);
/* Called to find the full path of files under the library directory. */
std::string library_file(struct library *, const std::string &);
#ifdef CONFIG_TESTING
const struct db_ops *test_library_ops();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_TAGS_LIBRARY_H */

View File

@ -99,4 +99,7 @@ void track_played(struct track *);
/* Called to find the date that this track was last played. */
const std::string track_last_play(struct track *);
#ifdef CONFIG_TESTING
const struct db_ops *test_track_ops();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_TAGS_TRACK_H */

View File

@ -32,6 +32,10 @@ struct int_entry : public db_entry {
};
static const struct db_ops int_ops = {
};
static void test_db_entry()
{
struct int_entry *ent = new struct int_entry(1);
@ -64,7 +68,7 @@ static void test_init()
{
database<struct int_entry> db;
db_init(&db, "init.db", false);
db_init(&db, "init.db", false, &int_ops);
/* Check initial sizes. */
test_equal(db.db_entries.size(), 0);
@ -85,7 +89,7 @@ static void test_stress(unsigned int N)
unsigned int i;
gchar *key;
db_init(&db, "stress.db", false);
db_init(&db, "stress.db", false, &int_ops);
/* db_insert() */
for (i = 0; i < N; i++) {
@ -185,8 +189,8 @@ static void test_save_load()
const unsigned int N = 10;
unsigned int i;
db_init(&db1, "save_load.db", true);
db_init(&db2, "save_load.db", false);
db_init(&db1, "save_load.db", true, &int_ops);
db_init(&db2, "save_load.db", false, &int_ops);
/* 10 items should "autosave" when inserted */
for (i = 0; i < N; i++)

View File

@ -62,6 +62,7 @@ static void test_album_compare()
static void test_album_db()
{
const struct db_ops *album_ops = test_album_ops();
database<struct album> album_db;
struct album *album;
@ -74,7 +75,7 @@ static void test_album_db()
test_equal(album_get(0), album);
test_equal(album_get(1), (struct album *)NULL);
db_init(&album_db, "album.db", false);
db_init(&album_db, "album.db", false, album_ops);
db_load(&album_db);
test_equal(album_db.db_size, 1);

View File

@ -63,6 +63,7 @@ static void test_artist_compare()
static void test_artist_db()
{
const struct db_ops *artist_ops = test_artist_ops();
database<struct artist> artist_db;
struct artist *artist;
@ -75,7 +76,7 @@ static void test_artist_db()
test_equal(artist_get(0), artist);
test_equal(artist_get(1), (struct artist *)NULL);
db_init(&artist_db, "artist.db", false);
db_init(&artist_db, "artist.db", false, artist_ops);
db_load(&artist_db);
test_equal(artist_db.db_size, 1);

View File

@ -63,6 +63,7 @@ static void test_genre_compare()
static void test_genere_db()
{
const struct db_ops *genre_ops = test_genre_ops();
database<struct genre> genre_db;
struct genre *genre;
@ -75,7 +76,7 @@ static void test_genere_db()
test_equal(genre_get(0), genre);
test_equal(genre_get(1), (struct genre *)NULL);
db_init(&genre_db, "genre.db", false);
db_init(&genre_db, "genre.db", false, genre_ops);
db_load(&genre_db);
test_equal(genre_db.db_size, 1);

View File

@ -64,6 +64,7 @@ static void test_library()
static void test_library_db()
{
const struct db_ops *library_ops = test_library_ops();
database<struct library> library_db;
struct library *library, *library2;
@ -79,7 +80,7 @@ static void test_library_db()
test_equal(library_get(0), library);
test_equal(library_get(1), (struct library *)NULL);
db_init(&library_db, "library.db", false);
db_init(&library_db, "library.db", false, library_ops);
db_load(&library_db);
test_equal(library_db.db_size, 1);
test_equal(db_actual_size(&library_db), 1);

View File

@ -163,6 +163,7 @@ static void test_track_db()
{
std::string path = "tests/Music/Hyrule Symphony/01 - Title Theme.ogg";
struct library *library = library_find("tests/Music");
const struct db_ops *track_ops = test_track_ops();
database<struct track> track_db;
struct track *track;
@ -174,7 +175,7 @@ static void test_track_db()
test_equal(track_get(1), NULL);
test_equal(track_db_get()->db_size, 1);
db_init(&track_db, "track.db", false);
db_init(&track_db, "track.db", false, track_ops);
db_load(&track_db);
test_equal(track_db.db_size, 0);