diff --git a/core/index.cpp b/core/index.cpp index a37c6331..83a2e844 100644 --- a/core/index.cpp +++ b/core/index.cpp @@ -9,11 +9,6 @@ index_entry :: index_entry() ie_set = SET_INIT(); } -index_entry :: ~index_entry() -{ - set_deinit(&ie_set); -} - static struct db_entry *index_alloc(const gchar *key) { struct index_entry *ent = new struct index_entry; @@ -21,6 +16,13 @@ static struct db_entry *index_alloc(const gchar *key) return ent; } +static void index_free(struct db_entry *dbe) +{ + struct index_entry *ent = (struct index_entry *)dbe; + set_deinit(&ent->ie_set); + delete (struct index_entry *)dbe; +} + const std::string index_entry :: primary_key() const { return ie_key; @@ -45,6 +47,7 @@ void index_entry :: read(file &file) static const struct db_ops index_ops = { index_alloc, + index_free, }; diff --git a/core/tags/album.cpp b/core/tags/album.cpp index 726050db..03c96708 100644 --- a/core/tags/album.cpp +++ b/core/tags/album.cpp @@ -43,6 +43,11 @@ static struct db_entry *album_alloc(const gchar *key) return album; } +static void album_free(struct db_entry *dbe) +{ + delete (struct album *)dbe; +} + const std::string album :: primary_key() const { return __album_key(al_name, al_year); @@ -63,6 +68,7 @@ void album :: write(file &file) static const struct db_ops album_ops = { album_alloc, + album_free, }; diff --git a/core/tags/artist.cpp b/core/tags/artist.cpp index aea835ec..3c2b74b8 100644 --- a/core/tags/artist.cpp +++ b/core/tags/artist.cpp @@ -24,6 +24,11 @@ static db_entry *artist_alloc(const gchar *name) return artist; } +static void artist_free(struct db_entry *dbe) +{ + delete (struct artist *)dbe; +} + const std::string artist :: primary_key() const { return ar_name; @@ -49,6 +54,7 @@ void artist :: write(file &file) static const struct db_ops artist_ops = { artist_alloc, + artist_free, }; diff --git a/core/tags/genre.cpp b/core/tags/genre.cpp index 62deee35..85f69aeb 100644 --- a/core/tags/genre.cpp +++ b/core/tags/genre.cpp @@ -23,6 +23,11 @@ static struct db_entry *genre_alloc(const gchar *name) return genre; } +static void genre_free(struct db_entry *dbe) +{ + delete (struct genre *)dbe; +} + const std::string genre :: primary_key() const { return ge_name; @@ -48,6 +53,7 @@ void genre :: write(file &file) static const struct db_ops genre_ops = { genre_alloc, + genre_free, }; diff --git a/core/tags/library.cpp b/core/tags/library.cpp index 7a647d15..c33fbc07 100644 --- a/core/tags/library.cpp +++ b/core/tags/library.cpp @@ -21,6 +21,11 @@ static struct db_entry *library_alloc(const gchar *path) return library; } +static void library_free(struct db_entry *dbe) +{ + delete (struct library *)dbe; +} + const std::string library :: primary_key() const { return li_path; @@ -47,6 +52,7 @@ void library :: write(file &file) static const struct db_ops library_ops = { library_alloc, + library_free, }; diff --git a/core/tags/track.cpp b/core/tags/track.cpp index fee7931f..d6e54a2e 100644 --- a/core/tags/track.cpp +++ b/core/tags/track.cpp @@ -82,10 +82,13 @@ out: g_free(path); } -track :: ~track() +static void track_free(struct db_entry *dbe) { - if (tr_library) - tr_library->li_size--; + struct track *track = (struct track *)dbe; + + if (track->tr_library) + track->tr_library->li_size--; + delete track; } const std::string track :: primary_key() const @@ -136,6 +139,8 @@ void track :: write(file &file) static const struct db_ops track_ops = { + NULL, + track_free, }; diff --git a/include/core/database.h b/include/core/database.h index 6cb861ca..0ee98514 100644 --- a/include/core/database.h +++ b/include/core/database.h @@ -53,6 +53,9 @@ struct db_entry { struct db_ops { /* Allocate a new struct db_entry from a given key. */ struct db_entry *(*dbe_alloc)(const gchar *); + + /* Free a struct db_entry. */ + void (*dbe_free)(struct db_entry *); }; diff --git a/include/core/database.hpp b/include/core/database.hpp index 3e3212ec..59e270b8 100644 --- a/include/core/database.hpp +++ b/include/core/database.hpp @@ -7,6 +7,18 @@ #ifndef OCARINA_DATABASE_HPP #define OCARINA_DATABASE_HPP + +template +static inline void __dbe_free(struct database *db, struct db_entry *dbe) +{ + if (dbe) { + db->db_keys.erase(dbe->primary_key()); + db->db_entries[dbe->dbe_index] = NULL; + db->db_size--; + db->db_ops->dbe_free(dbe); + } +} + template void db_init(struct database *db, const char *filepath, bool autosave, const struct db_ops *ops) @@ -20,12 +32,9 @@ void db_init(struct database *db, const char *filepath, bool autosave, template void db_deinit(struct database *db) { - T *t, *u; - db_for_each(t, u, db) { - db->db_entries[t->dbe_index] = NULL; - delete t; - db->db_size--; - } + T *dbe, *next; + db_for_each(dbe, next, db) + __dbe_free(db, dbe); } template @@ -106,10 +115,7 @@ void db_remove(struct database *db, T *item) return; if (db_at(db, item->dbe_index) != item) return; - db->db_entries[item->dbe_index] = NULL; - db->db_keys.erase(item->primary_key()); - delete item; - db->db_size--; + __dbe_free(db, item); db_autosave(db); } diff --git a/include/core/index.h b/include/core/index.h index a63a29ff..658d1e73 100644 --- a/include/core/index.h +++ b/include/core/index.h @@ -21,7 +21,6 @@ struct index_entry : public db_entry { struct set ie_set; index_entry(); /**< Create an empty IndexEntry. */ - ~index_entry(); /** * Access the key stored by this IndexEntry. diff --git a/include/core/tags/track.h b/include/core/tags/track.h index 3915b2f1..a3af21d7 100644 --- a/include/core/tags/track.h +++ b/include/core/tags/track.h @@ -35,7 +35,6 @@ struct track : public db_entry { track(const std::string &); track(); /**< Track constructor. */ - ~track(); /**< Track destructor. */ /** diff --git a/tests/core/database.cpp b/tests/core/database.cpp index c3f138ed..e434f3b1 100644 --- a/tests/core/database.cpp +++ b/tests/core/database.cpp @@ -30,6 +30,8 @@ struct int_entry : public db_entry { void read(file &f) { file_readf(&f, "%u", &ie_val); } }; +unsigned int test_free_count = 0; + static struct db_entry *int_alloc(const gchar *key) { struct int_entry *ent = new int_entry; @@ -37,9 +39,15 @@ static struct db_entry *int_alloc(const gchar *key) return ent; } +static void int_free(struct db_entry *dbe) +{ + test_free_count++; + delete (struct int_entry *)dbe; +} static const struct db_ops int_ops = { int_alloc, + int_free, }; @@ -57,7 +65,9 @@ static void test_db_entry() file_open(&f, OPEN_WRITE); ent->write(f); file_close(&f); - delete ent; + + int_ops.dbe_free(ent); + test_equal(test_free_count, 1); ent = new int_entry(); test_equal(ent->ie_val, 0); @@ -69,7 +79,8 @@ static void test_db_entry() test_equal(ent->ie_val, 1); test_equal(ent->primary_key(), "1"); - delete ent; + int_ops.dbe_free(ent); + test_equal(test_free_count, 2); } static void test_init() @@ -97,6 +108,7 @@ static void test_stress(unsigned int N) unsigned int i; gchar *key; + test_free_count = 0; db_init(&db, "stress.db", false, &int_ops); /* db_insert() */ @@ -162,6 +174,7 @@ static void test_stress(unsigned int N) db_remove(&db, &rmv); test_equal(db.db_size, N / 2); test_equal(db_actual_size(&db), N + 1); + test_equal(test_free_count, (N / 2) + 1); /* db_for_each() (db_first() / db_next()) */ i = 1; @@ -184,6 +197,7 @@ static void test_stress(unsigned int N) test_equal(db.db_size, 0); test_equal(db_actual_size(&db), N + 1); test_equal(db_first(&db), NULL); + test_equal(test_free_count, N + 1); } static void test_basics() { test_stress(10); } diff --git a/tests/core/index.cpp b/tests/core/index.cpp index 9ea6290e..acf24d38 100644 --- a/tests/core/index.cpp +++ b/tests/core/index.cpp @@ -8,12 +8,13 @@ static void test_entry() { + const struct db_ops *index_ops = test_index_ops(); struct set_iter it; index_entry *ie; unsigned int i; struct file f; - ie = (index_entry *)test_index_ops()->dbe_alloc("Link"); + ie = (index_entry *)index_ops->dbe_alloc("Link"); test_equal(ie->primary_key(), "Link"); set_insert(&ie->ie_set, 0); set_insert(&ie->ie_set, 1); @@ -30,7 +31,7 @@ static void test_entry() file_writef(&f, "Zelda\n0 \n"); ie->write(f); file_close(&f); - delete ie; + index_ops->dbe_free(ie); ie = new index_entry(); test_equal(ie->primary_key(), ""); @@ -52,7 +53,7 @@ static void test_entry() i++; } test_loop_passed(); - delete ie; + index_ops->dbe_free(ie); } static void test_stress(unsigned int N) diff --git a/tests/core/tags/album.cpp b/tests/core/tags/album.cpp index 430ff106..ba4b046f 100644 --- a/tests/core/tags/album.cpp +++ b/tests/core/tags/album.cpp @@ -34,7 +34,7 @@ static void test_album() file_writef(&f, "0 \n"); album->write(f); file_close(&f); - delete album; + album_ops->dbe_free(album); album = new struct album(); test_verify_empty(album); @@ -46,7 +46,7 @@ static void test_album() album->read(f); file_close(&f); test_verify_hyrule(album); - delete album; + album_ops->dbe_free(album); } static void test_album_compare() @@ -61,8 +61,8 @@ static void test_album_compare() test_equal(album_compare(twilight, skyward), 1); test_equal(album_compare(skyward, twilight), -1); - delete skyward; - delete twilight; + album_ops->dbe_free(twilight); + album_ops->dbe_free(skyward); } static void test_album_db() diff --git a/tests/core/tags/artist.cpp b/tests/core/tags/artist.cpp index ad822a1f..175653ad 100644 --- a/tests/core/tags/artist.cpp +++ b/tests/core/tags/artist.cpp @@ -33,7 +33,7 @@ static void test_artist() file_writef(&f, "1 \n1 "); artist->write(f); file_close(&f); - delete artist; + artist_ops->dbe_free(artist); artist = new struct artist(); test_verify_empty(artist); @@ -47,7 +47,7 @@ static void test_artist() artist->read(f); file_close(&f); test_verify_koji(artist); - delete artist; + artist_ops->dbe_free(artist); } static void test_artist_compare() @@ -62,8 +62,8 @@ static void test_artist_compare() test_equal(artist_compare(koji, hajime), 1); test_equal(artist_compare(hajime, koji), -1); - delete hajime; - delete koji; + artist_ops->dbe_free(koji); + artist_ops->dbe_free(hajime); } static void test_artist_db() diff --git a/tests/core/tags/genre.cpp b/tests/core/tags/genre.cpp index 412074d8..b7023e5e 100644 --- a/tests/core/tags/genre.cpp +++ b/tests/core/tags/genre.cpp @@ -33,7 +33,7 @@ static void test_genre() file_writef(&f, "1 \n1 "); genre->write(f); file_close(&f); - delete genre; + genre_ops->dbe_free(genre); genre = new struct genre(); test_verify_empty(genre); @@ -47,7 +47,7 @@ static void test_genre() genre->read(f); file_close(&f); test_verify_vg(genre); - delete genre; + genre_ops->dbe_free(genre); } static void test_genre_compare() @@ -62,8 +62,8 @@ static void test_genre_compare() test_equal(genre_compare(video, game), 1); test_equal(genre_compare(game, video), -1); - delete game; - delete video; + genre_ops->dbe_free(video); + genre_ops->dbe_free(game); } static void test_genere_db() diff --git a/tests/core/tags/library.cpp b/tests/core/tags/library.cpp index e8dbaf76..e979e4fc 100644 --- a/tests/core/tags/library.cpp +++ b/tests/core/tags/library.cpp @@ -59,9 +59,9 @@ static void test_library() test_verify_zelda(library); test_equal(library_file(library, "impa.ogg"), "/home/Zelda/Music/impa.ogg"); - delete library; - delete zelda; - delete link; + library_ops->dbe_free(link); + library_ops->dbe_free(zelda); + library_ops->dbe_free(library); } static void test_library_db() diff --git a/tests/core/tags/track.cpp b/tests/core/tags/track.cpp index 2b983b14..ab64f489 100644 --- a/tests/core/tags/track.cpp +++ b/tests/core/tags/track.cpp @@ -75,6 +75,7 @@ static void test_verify_notrack(struct track *track) static void test_track() { + const struct db_ops *track_ops = test_track_ops(); time_t rawtime = time(NULL); struct tm *now = localtime(&rawtime); struct track *track = new struct track;; @@ -83,7 +84,7 @@ static void test_track() file f; test_verify_empty(track); - delete track; + track_ops->dbe_free(track); std::setlocale(LC_TIME, "C"); filter_init(); @@ -102,7 +103,7 @@ static void test_track() track->write(f); file_close(&f); - delete track; + track_ops->dbe_free(track); test_equal(library->li_size, 0); track = new struct track; @@ -110,7 +111,7 @@ static void test_track() track->read(f); test_verify_notrack(track); test_equal(library->li_size, 1); - delete track; + track_ops->dbe_free(track); track = new struct track; track->read(f); @@ -122,7 +123,7 @@ static void test_track() test_equal(track->tr_count, 1); test_equal(track_last_play(track), date); - delete track; + track_ops->dbe_free(track); g_free(date); } @@ -148,6 +149,7 @@ static void test_track_filter() static void test_track_compare() { + const struct db_ops *track_ops = test_track_ops(); struct track *title = new struct track("0/Hyrule Symphony/01 - Title Theme.ogg"); struct track *kokiri = new struct track("0/Hyrule Symphony/02 - Kokiri Forest.ogg"); @@ -155,8 +157,8 @@ static void test_track_compare() test_equal(track_compare(kokiri, title), -1); test_equal(track_compare(title, kokiri), 1); - delete title; - delete kokiri; + track_ops->dbe_free(title); + track_ops->dbe_free(kokiri); } static void test_track_db()