diff --git a/core/index.cpp b/core/index.cpp index cab46c79..8ebb0078 100644 --- a/core/index.cpp +++ b/core/index.cpp @@ -77,7 +77,7 @@ void Index :: insert(const std::string &key, unsigned int value) { IndexEntry *it = find(key); if (it == NULL) - it = database :: insert(IndexEntry(key)); + it = db_insert(this, new IndexEntry(key)); it->insert(value); ::db_autosave(this); diff --git a/core/tags/album.cpp b/core/tags/album.cpp index 7b820e03..465adcd4 100644 --- a/core/tags/album.cpp +++ b/core/tags/album.cpp @@ -58,7 +58,7 @@ Album *tags :: get_album(const std::string &name, unsigned int year) Album *ret = album_db.find(make_key(name, year)); if (ret) return ret; - return album_db.insert(Album(name, year)); + return db_insert(&album_db, new Album(name, year)); } Album *tags ::get_album(const unsigned int index) diff --git a/core/tags/artist.cpp b/core/tags/artist.cpp index e17023fa..2cce05e2 100644 --- a/core/tags/artist.cpp +++ b/core/tags/artist.cpp @@ -25,7 +25,7 @@ Artist *tags :: get_artist(const std::string &name) Artist *ret = artist_db.find(name); if (ret) return ret; - return artist_db.insert(Artist(name)); + return db_insert(&artist_db, new Artist(name)); } Artist *tags :: get_artist(const unsigned int index) diff --git a/core/tags/genre.cpp b/core/tags/genre.cpp index 658dc2f7..1b5722af 100644 --- a/core/tags/genre.cpp +++ b/core/tags/genre.cpp @@ -25,7 +25,7 @@ Genre *tags :: get_genre(const std::string &name) Genre *ret = genre_db.find(name); if (ret) return ret; - return genre_db.insert(Genre(name)); + return db_insert(&genre_db, new Genre(name)); } Genre *tags :: get_genre(const unsigned int index) diff --git a/core/tags/library.cpp b/core/tags/library.cpp index cd91fb31..5e6a7d31 100644 --- a/core/tags/library.cpp +++ b/core/tags/library.cpp @@ -77,7 +77,7 @@ Library *tags :: get_library(const std::string &path) Library *ret = library_db.find(path); if (ret) return ret; - return library_db.insert(Library(path)); + return db_insert(&library_db, new Library(path)); } Library *tags :: get_library(const unsigned int index) diff --git a/core/tags/track.cpp b/core/tags/track.cpp index f85539c7..4e61aaa2 100644 --- a/core/tags/track.cpp +++ b/core/tags/track.cpp @@ -10,6 +10,19 @@ static database track_db("track.db", false); +static const std::string make_key(Library *library, const std::string &path) +{ + std :: string res; + + if (library) { + gchar *g_res = g_strdup_printf("%u/%s", library->index(), + path.c_str()); + res = g_res; + g_free(g_res); + } + + return res; +} Track :: Track() : GenericTag(), @@ -77,16 +90,7 @@ const std::string Track :: path() const const std::string Track :: primary_key() const { - std :: string res; - - if (_library) { - gchar *g_res = g_strdup_printf("%u/%s", _library->index(), - _path.c_str()); - res = g_res; - g_free(g_res); - } - - return res; + return make_key(_library, _path); } void Track :: played() @@ -149,8 +153,11 @@ Track *tags :: add_track(Album *album, Artist *artist, Genre *genre, unsigned int track) { std::string path = filepath.substr(library->primary_key().size() + 1); - return track_db.insert(Track(album, artist, genre, library, path, - name, length, track)); + Track *ret = track_db.find(make_key(library, path)); + if (ret) + return NULL; + return db_insert(&track_db, new Track(album, artist, genre, library, + path, name, length, track)); } Track *tags :: get_track(const unsigned int index) diff --git a/include/core/database.h b/include/core/database.h index 58d2ad9c..6db300c5 100644 --- a/include/core/database.h +++ b/include/core/database.h @@ -108,23 +108,6 @@ struct database { ~database(); - /** - * Called to add a new item to the Database. Upon successful insertion, - * this function will: - * -# Allocate a new DatabaseEntry instance. - * -# Set the DatabaseEntry::_index field to the size of Database::_db. - * -# Add the new DatabaseEntry to the end of Database::_db. - * -# Increment Database::_size. - * -# Call Database::autosave() to commit changes. - * - * @param item The new item to be added. - * @return If Database::_keys already contains an instance with the - * same DatabaseEntry::primary_key(), then return NULL. - * @return Otherwise, return a pointer to the new instance stored - * in the Database. - */ - T *insert(const T &); - /** * Called to remove an item from the Database. This function will: * -# Delete memory allocated for the DatabaseEntry @@ -189,6 +172,15 @@ void db_load(struct database *); template unsigned int db_actual_size(const struct database *); + +/* + * Called to add a new item to the database. The caller MUST check if the + * database already contains a similar item before calling this function. + */ +template +T *db_insert(struct database *, T *); + + #include "database.hpp" #endif /* OCARINA_CORE_DATABASE_H */ diff --git a/include/core/database.hpp b/include/core/database.hpp index 58662e38..bde68367 100644 --- a/include/core/database.hpp +++ b/include/core/database.hpp @@ -79,21 +79,18 @@ void db_load(struct database *db) } template -T *database :: insert(const T &item) +T *db_insert(struct database *db, T *item) { - T *t = find(item.primary_key()); - - if (t != NULL) + if (!item) return NULL; - t = new T(item); - t->_index = db_actual_size(this); - db_entries.push_back(t); + item->_index = db_actual_size(db); + db->db_entries.push_back(item); - db_keys[t->primary_key()] = t->index(); - db_size++; - ::db_autosave(this); - return t; + db->db_keys[item->primary_key()] = item->index(); + db->db_size++; + db_autosave(db); + return db->db_entries[item->_index]; } template diff --git a/tests/core/database.cpp b/tests/core/database.cpp index 0343bdc8..ad88fbff 100644 --- a/tests/core/database.cpp +++ b/tests/core/database.cpp @@ -77,16 +77,17 @@ static void test_stress(unsigned int N) unsigned int i; gchar *key; - /* database.insert() */ + /* db_insert() */ for (i = 0; i < N; i++) { - dbe = db.insert(int_entry(i)); + dbe = db_insert(&db, new int_entry(i)); test_loop_not_equal(dbe, NULL, i); - test_loop_equal(db.insert(int_entry(i)), NULL, i); test_loop_equal(dbe->index(), i, i); test_loop_equal(dbe->ie_val, i, i); ptrs.push_back(dbe); } test_loop_passed(); + dbe = db_insert(&db, (struct int_entry *)NULL); + test_equal(dbe, NULL); test_equal(db.db_size, N); test_equal(db_actual_size(&db), N); @@ -151,7 +152,7 @@ static void test_save_load() /* 10 items should "autosave" when inserted */ for (i = 0; i < N; i++) - db1.insert(int_entry(i)); + db_insert(&db1, new int_entry(i)); db_load(&db2); test_equal(db2.db_size, N); @@ -181,7 +182,7 @@ static void test_save_load() /* Test with autosave turned off. */ for (i = N; i < (2 * N); i++) - db2.insert(int_entry(i)); + db_insert(&db2, new int_entry(i)); for (i = N; i < (2 * N); i += 2) db2.remove(i);