core/database: Move db_find() out of the database struct
I also take the chance to modify this function slightly. Now, if a matching item could not be found a new item will be allocated. I added the new function db_get() if callers just want to get an item without allocating. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
f2f23cb225
commit
ffd38bd28b
|
@ -54,7 +54,7 @@ void filter :: search(const std::string &text, std::set<unsigned int> &res)
|
|||
if (end == std::string::npos)
|
||||
end = lc.size();
|
||||
|
||||
found = filter_index.find(lc.substr(begin, end - begin));
|
||||
found = db_get(&filter_index, lc.substr(begin, end- begin).c_str());
|
||||
if (!found) {
|
||||
res.clear();
|
||||
return;
|
||||
|
|
|
@ -75,21 +75,16 @@ Index :: Index(const std::string &filepath, bool autosave)
|
|||
|
||||
void Index :: insert(const std::string &key, unsigned int value)
|
||||
{
|
||||
IndexEntry *it = find(key);
|
||||
if (it == NULL)
|
||||
it = db_insert(this, new IndexEntry(key));
|
||||
|
||||
IndexEntry *it = db_find(this, key.c_str());
|
||||
it->insert(value);
|
||||
::db_autosave(this);
|
||||
}
|
||||
|
||||
void Index :: remove(const std::string &key, unsigned int value)
|
||||
{
|
||||
IndexEntry *it = find(key);
|
||||
|
||||
if (it == NULL)
|
||||
return;
|
||||
|
||||
it->remove(value);
|
||||
::db_autosave(this);
|
||||
IndexEntry *it = db_get(this, key.c_str());
|
||||
if (it) {
|
||||
it->remove(value);
|
||||
::db_autosave(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ void playlist :: init()
|
|||
bool playlist :: has(Track *track, const std::string &name)
|
||||
{
|
||||
std::set<unsigned int>::iterator it;
|
||||
IndexEntry *ent = playlist_db.find(name);
|
||||
IndexEntry *ent = db_get(&playlist_db, name.c_str());
|
||||
|
||||
if (ent == NULL)
|
||||
return false;
|
||||
|
@ -132,7 +132,7 @@ void playlist :: del(Track *track, const std::string &name)
|
|||
|
||||
void playlist :: select(const std::string &name)
|
||||
{
|
||||
IndexEntry *ent = playlist_db.find(name);
|
||||
IndexEntry *ent = db_get(&playlist_db, name.c_str());
|
||||
|
||||
if (ent != NULL)
|
||||
playlist_q.fill(ent);
|
||||
|
@ -144,7 +144,7 @@ void playlist :: select(const std::string &name)
|
|||
|
||||
IndexEntry *playlist :: get_tracks(const std::string &name)
|
||||
{
|
||||
return playlist_db.find(name);
|
||||
return db_get(&playlist_db, name.c_str());
|
||||
}
|
||||
|
||||
Queue *playlist :: get_queue()
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/**
|
||||
* Copyright 2014 (c) Anna Schumaker.
|
||||
*/
|
||||
extern "C" {
|
||||
#include <core/string.h>
|
||||
}
|
||||
#include <core/tags/album.h>
|
||||
#include <glib.h>
|
||||
|
||||
|
@ -25,6 +27,19 @@ Album :: Album(const std::string &name, unsigned int year)
|
|||
{
|
||||
}
|
||||
|
||||
Album :: Album(const std::string &key)
|
||||
{
|
||||
gchar *name, *lower;
|
||||
sscanf(key.c_str(), "%u/%m[^\n]", &_year, &name);
|
||||
|
||||
lower = string_lowercase(name);
|
||||
_name = name;
|
||||
_lower = lower;
|
||||
|
||||
g_free(name);
|
||||
g_free(lower);
|
||||
}
|
||||
|
||||
const std::string Album :: primary_key() const
|
||||
{
|
||||
return make_key(GenericTag :: primary_key(), _year);
|
||||
|
@ -55,10 +70,7 @@ void tags :: init_album_db()
|
|||
|
||||
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 db_insert(&album_db, new Album(name, year));
|
||||
return db_find(&album_db, make_key(name, year).c_str());
|
||||
}
|
||||
|
||||
Album *tags ::get_album(const unsigned int index)
|
||||
|
|
|
@ -22,10 +22,7 @@ void tags :: init_artist_db()
|
|||
|
||||
Artist *tags :: get_artist(const std::string &name)
|
||||
{
|
||||
Artist *ret = artist_db.find(name);
|
||||
if (ret)
|
||||
return ret;
|
||||
return db_insert(&artist_db, new Artist(name));
|
||||
return db_find(&artist_db, name.c_str());
|
||||
}
|
||||
|
||||
Artist *tags :: get_artist(const unsigned int index)
|
||||
|
|
|
@ -22,10 +22,7 @@ void tags :: init_genre_db()
|
|||
|
||||
Genre *tags :: get_genre(const std::string &name)
|
||||
{
|
||||
Genre *ret = genre_db.find(name);
|
||||
if (ret)
|
||||
return ret;
|
||||
return db_insert(&genre_db, new Genre(name));
|
||||
return db_find(&genre_db, name.c_str());
|
||||
}
|
||||
|
||||
Genre *tags :: get_genre(const unsigned int index)
|
||||
|
|
|
@ -74,10 +74,7 @@ void tags :: init_library_db()
|
|||
|
||||
Library *tags :: get_library(const std::string &path)
|
||||
{
|
||||
Library *ret = library_db.find(path);
|
||||
if (ret)
|
||||
return ret;
|
||||
return db_insert(&library_db, new Library(path));
|
||||
return db_find(&library_db, path.c_str());
|
||||
}
|
||||
|
||||
Library *tags :: get_library(const unsigned int index)
|
||||
|
|
|
@ -153,8 +153,7 @@ Track *tags :: add_track(Album *album, Artist *artist, Genre *genre,
|
|||
unsigned int track)
|
||||
{
|
||||
std::string path = filepath.substr(library->primary_key().size() + 1);
|
||||
Track *ret = track_db.find(make_key(library, path));
|
||||
if (ret)
|
||||
if (db_get(&track_db, make_key(library, path).c_str()))
|
||||
return NULL;
|
||||
return db_insert(&track_db, new Track(album, artist, genre, library,
|
||||
path, name, length, track));
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
unsigned int _index; /**< The location of an item in the Database. */
|
||||
|
||||
DatabaseEntry(); /**< Initialize _index to 0. */
|
||||
DatabaseEntry(const std::string);
|
||||
virtual ~DatabaseEntry() = 0; /**< Virtual destructor */
|
||||
|
||||
/**
|
||||
|
@ -123,15 +124,6 @@ struct database {
|
|||
* @return An iterator pointing to the next valid item in the database.
|
||||
*/
|
||||
iterator next(iterator &);
|
||||
|
||||
/**
|
||||
* Find a DatabaseItem with a specific primary key.
|
||||
*
|
||||
* @param key The key to search for.
|
||||
* @return A pointer to the requested DatabaseEntry.
|
||||
* @return NULL if there is no matching DatabaseEntry.
|
||||
*/
|
||||
T *find(const std::string &);
|
||||
};
|
||||
|
||||
|
||||
|
@ -168,6 +160,17 @@ void db_remove(struct database<T> *, T *);
|
|||
template <class T>
|
||||
T *db_at(struct database<T> *, unsigned int);
|
||||
|
||||
/* Returns the database item with the specified key. */
|
||||
template <class T>
|
||||
T *db_get(struct database<T> *, const gchar *);
|
||||
|
||||
/*
|
||||
* Similar to db_get(), but allocate and return a new item if the
|
||||
* database doesn't contain an item with the specified key.
|
||||
*/
|
||||
template <class T>
|
||||
T *db_find(struct database<T> *, const gchar *);
|
||||
|
||||
#include "database.hpp"
|
||||
|
||||
#endif /* OCARINA_CORE_DATABASE_H */
|
||||
|
|
|
@ -149,12 +149,21 @@ T *db_at(struct database<T> *db, unsigned int index)
|
|||
}
|
||||
|
||||
template <class T>
|
||||
T *database<T> :: find(const std::string &key)
|
||||
T *db_get(struct database<T> *db, const gchar *key)
|
||||
{
|
||||
std::map<const std::string, unsigned int>::iterator it;
|
||||
it = db_keys.find(key);
|
||||
if (it == db_keys.end())
|
||||
it = db->db_keys.find(key);
|
||||
if (it == db->db_keys.end())
|
||||
return NULL;
|
||||
return db_entries[it->second];
|
||||
return db->db_entries[it->second];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *db_find(struct database<T> *db, const gchar *key)
|
||||
{
|
||||
T *dbe = db_get(db, key);
|
||||
if (dbe)
|
||||
return dbe;
|
||||
return db_insert(db, new T(key));
|
||||
}
|
||||
#endif /* OCARINA_DATABASE_HPP */
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
* @param year Album year
|
||||
*/
|
||||
Album(const std::string &, unsigned int);
|
||||
Album(const std::string &);
|
||||
|
||||
/**
|
||||
* The album's primary key is the concatenation of year
|
||||
|
|
|
@ -20,11 +20,10 @@
|
|||
|
||||
*/
|
||||
class GenericTag : public DatabaseEntry {
|
||||
private:
|
||||
public:
|
||||
std::string _name; /**< The name associated with this tag. */
|
||||
std::string _lower; /**< The lowercase form of GenericTag::_name. */
|
||||
|
||||
public:
|
||||
GenericTag(); /**< GenericTag constructor. */
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@ struct int_entry : public DatabaseEntry {
|
|||
|
||||
int_entry() : ie_val(0) {};
|
||||
int_entry(unsigned int v) : ie_val(v) {};
|
||||
int_entry(const std::string &k) { sscanf(k.c_str(), "%u", &ie_val); }
|
||||
|
||||
const std::string primary_key() const
|
||||
{
|
||||
|
@ -100,10 +101,10 @@ static void test_stress(unsigned int N)
|
|||
} test_loop_passed();
|
||||
test_equal(db_at(&db, N), NULL);
|
||||
|
||||
/* database.find() */
|
||||
/* db_get() */
|
||||
for (i = 0; i < N; i++) {
|
||||
key = g_strdup_printf("%u", i);
|
||||
dbe = db.find(key);
|
||||
dbe = db_get(&db, key);
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_equal(dbe->primary_key(), key, i);
|
||||
test_loop_equal(dbe, ptrs.at(i), i);
|
||||
|
@ -111,21 +112,35 @@ static void test_stress(unsigned int N)
|
|||
g_free(key);
|
||||
} test_loop_passed();
|
||||
key = g_strdup_printf("%u", N);
|
||||
test_equal(db.find(key), NULL);
|
||||
test_equal(db_get(&db, key), NULL);
|
||||
g_free(key);
|
||||
|
||||
/* db_find() */
|
||||
for (i = 0; i <= N; i++) {
|
||||
key = g_strdup_printf("%u", i);
|
||||
dbe = db_find(&db, key);
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_equal(dbe->primary_key(), key, i);
|
||||
test_loop_equal(dbe->ie_val, i, i);
|
||||
if (i < N)
|
||||
test_loop_equal(dbe, ptrs.at(i), i);
|
||||
g_free(key);
|
||||
} test_loop_passed();
|
||||
test_equal(db.db_size, N + 1);
|
||||
test_equal(db_actual_size(&db), N + 1);
|
||||
|
||||
/* db_remove(): Even indices only! */
|
||||
for (i = 0; i <= (N + 2); i += 2) {
|
||||
key = g_strdup_printf("%u", i);
|
||||
dbe = db.find(key);
|
||||
dbe = db_get(&db, key);
|
||||
db_remove(&db, dbe);
|
||||
test_loop_equal(db_at(&db, i), NULL, i);
|
||||
test_loop_equal(db.find(key), NULL, i);
|
||||
test_loop_equal(db_get(&db, key), NULL, i);
|
||||
g_free(key);
|
||||
} test_loop_passed();
|
||||
db_remove(&db, &rmv);
|
||||
test_equal(db.db_size, N / 2);
|
||||
test_equal(db_actual_size(&db), N);
|
||||
test_equal(db_actual_size(&db), N + 1);
|
||||
|
||||
/* database.first(), database.next(), database.end() */
|
||||
i = 1;
|
||||
|
|
|
@ -16,7 +16,7 @@ static void test_single_item()
|
|||
Index index("index.idx", false);
|
||||
|
||||
index.insert("a", 0);
|
||||
IndexEntry *it = index.find("a");
|
||||
IndexEntry *it = db_get(&index, "a");
|
||||
|
||||
test_not_equal(it, (IndexEntry *)NULL);
|
||||
test_equal(index.db_size, (unsigned)1);
|
||||
|
@ -42,7 +42,7 @@ static void test_insertion(unsigned int n)
|
|||
test_equal(INDEX->db_size, (n == 0) ? 0 : 26);
|
||||
|
||||
for (char c = 'a'; c <= 'z'; c++) {
|
||||
IndexEntry *it = INDEX->find(std::string(1, c));
|
||||
IndexEntry *it = db_get(INDEX, std::string(1, c).c_str());
|
||||
if (n == 0) {
|
||||
test_loop_equal(it, NULL, c - 'a');
|
||||
return;
|
||||
|
@ -61,7 +61,7 @@ static void test_removal(unsigned int n)
|
|||
for (unsigned int i = 0; i < n; i++)
|
||||
INDEX->remove(std::string(1, c), i);
|
||||
|
||||
it = INDEX->find(std::string(1, c));
|
||||
it = db_get(INDEX, std::string(1, c).c_str());
|
||||
if (n == 0) {
|
||||
test_loop_equal(it, NULL, c - 'a');
|
||||
return;
|
||||
|
@ -87,8 +87,8 @@ static void test_save_load(unsigned int n)
|
|||
test_equal(db_actual_size(&idx2), db_actual_size(INDEX));
|
||||
|
||||
for (char c = 'a'; c <= 'z'; c++) {
|
||||
it1 = INDEX->find(std::string(1, c));
|
||||
it2 = idx2.find(std::string(1, c));
|
||||
it1 = db_get(INDEX, std::string(1, c).c_str());
|
||||
it2 = db_get(&idx2, std::string(1, c).c_str());
|
||||
if (n == 0) {
|
||||
test_loop_equal(it1, NULL, c - 'a');
|
||||
test_loop_equal(it2, NULL, c - 'a');
|
||||
|
|
Loading…
Reference in New Issue