database: Return pointers for insert() at() and find()

This gives me the item directly, which is usually what I want when I
call these functions.  Save iterators for iterating.

Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
This commit is contained in:
Anna Schumaker 2014-03-24 19:51:13 -04:00 committed by Anna Schumaker
parent e2560f3134
commit 38990748bb
11 changed files with 60 additions and 63 deletions

20
DESIGN
View File

@ -280,7 +280,7 @@ Database:
void save(); void save();
void load(); void load();
iterator insert(T); T *insert(T);
void remove(unsigned int); void remove(unsigned int);
unsigned int size(); unsigned int size();
unsigned int actual_size(); unsigned int actual_size();
@ -289,8 +289,8 @@ Database:
iterator end(); iterator end();
iterator next(iterator &); iterator next(iterator &);
iterator at(unsigned int); T *at(unsigned int);
iterator find(const std::string &); T *find(const std::string &);
}; };
- File format: - File format:
@ -311,7 +311,7 @@ Database:
void Database :: load(); void Database :: load();
Load the database from disk. Load the database from disk.
iterator Database :: insert(T &item); T *Database :: insert(T &item);
Look up the item in the _keys map. Look up the item in the _keys map.
If we find an item with the same key: If we find an item with the same key:
- Return an iterator to the found item. - Return an iterator to the found item.
@ -350,17 +350,17 @@ Database:
Return the next DatabaseEntry with valid == true or _db.end() Return the next DatabaseEntry with valid == true or _db.end()
if there are no valid entries left. if there are no valid entries left.
iterator Database :: at(unsigned int i); T *Database :: at(unsigned int i);
If _db[i].valid == true: If _db[i].valid == true:
Return an iterator pointing to _db[i]; Return a pointer to _db[i];
Otherwise: Otherwise:
Return _db.end(); Return NULL;
iterator Database :: find(const std::string &key); T *Database :: find(const std::string &key);
If key is in the _keys map: If key is in the _keys map:
Return an iterator pointing to the corresponding entry. Return a pointer to the corresponding entry.
Otherwise: Otherwise:
Return _db.end(); Return NULL;

View File

@ -43,7 +43,7 @@ public:
void autosave(); void autosave();
void load(); void load();
iterator insert(T); T *insert(T);
void remove(unsigned int); void remove(unsigned int);
unsigned int size(); unsigned int size();
unsigned int actual_size(); unsigned int actual_size();
@ -52,8 +52,8 @@ public:
iterator end(); iterator end();
iterator next(iterator &); iterator next(iterator &);
iterator at(unsigned int); T *at(unsigned int);
iterator find(const std::string &); T *find(const std::string &);
}; };
#include "database.hpp" #include "database.hpp"

View File

@ -72,21 +72,21 @@ void Database<T> :: load()
} }
template <class T> template <class T>
typename Database<T>::iterator Database<T> :: insert(T val) T *Database<T> :: insert(T val)
{ {
iterator it = find(val.primary_key()); T *t = find(val.primary_key());
if (it != end()) if (t != NULL)
return it; return t;
it = _db.insert(_db.end(), val); iterator it = _db.insert(_db.end(), val);
it->valid = true; it->valid = true;
it->id = it - _db.begin(); it->id = it - _db.begin();
_keys[it->primary_key()] = it->id; _keys[it->primary_key()] = it->id;
_size++; _size++;
autosave(); autosave();
return it; return &_db[it->id];
} }
template <class T> template <class T>
@ -142,23 +142,23 @@ typename Database<T>::iterator Database<T> :: next(iterator &it)
} }
template <class T> template <class T>
typename Database<T>::iterator Database<T> :: at(unsigned int id) T *Database<T> :: at(unsigned int id)
{ {
if (id >= actual_size()) if (id >= actual_size())
return end(); return NULL;
if (_db[id].valid == false) if (_db[id].valid == false)
return end(); return NULL;
return _db.begin() + id; return &_db[id];
} }
template <class T> template <class T>
typename Database<T>::iterator Database<T> :: find(const std::string &key) T *Database<T> :: find(const std::string &key)
{ {
std::map<const std::string, unsigned int>::iterator it; std::map<const std::string, unsigned int>::iterator it;
it = _keys.find(key); it = _keys.find(key);
if (it == _keys.end()) if (it == _keys.end())
return end(); return NULL;
return _db.begin() + it->second; return &_db[it->second];
} }
#endif /* OCARINA_DATABASE_HPP */ #endif /* OCARINA_DATABASE_HPP */

View File

@ -93,7 +93,7 @@ std::string filter :: add(const std::string &text, unsigned int track_id)
static void find_intersection(std::string &text, std::set<unsigned int> &res) static void find_intersection(std::string &text, std::set<unsigned int> &res)
{ {
Index::iterator it = filter_index.find(text); IndexEntry *it = filter_index.find(text);
std::set<unsigned int> tmp; std::set<unsigned int> tmp;
set_intersection(it->values.begin(), it->values.end(), set_intersection(it->values.begin(), it->values.end(),

View File

@ -51,8 +51,8 @@ Index :: Index(const std::string &filepath, bool autosave)
void Index :: insert(const std::string &key, unsigned int val) void Index :: insert(const std::string &key, unsigned int val)
{ {
iterator it = find(key); IndexEntry *it = find(key);
if (it == end()) if (it == NULL)
it = Database :: insert(IndexEntry(key)); it = Database :: insert(IndexEntry(key));
it->insert(val); it->insert(val);
@ -61,9 +61,9 @@ void Index :: insert(const std::string &key, unsigned int val)
void Index :: remove(const std::string &key, unsigned int val) void Index :: remove(const std::string &key, unsigned int val)
{ {
iterator it = find(key); IndexEntry *it = find(key);
if (it == end()) if (it == NULL)
return; return;
it->remove(val); it->remove(val);

View File

@ -305,7 +305,7 @@ static bool process_path(unsigned int lib_id, const std :: string &dir,
scan.path = path; scan.path = path;
idle :: schedule (do_scan_path, scan); idle :: schedule (do_scan_path, scan);
} else { } else {
if (track_db.find(path) == track_db.end()) { if (track_db.find(path) == NULL) {
read_tags(lib_id, path); read_tags(lib_id, path);
changed = true; changed = true;
} }
@ -435,7 +435,7 @@ static void do_import_library(std::string &s)
f >> id >> enabled >> next_id >> size; f >> id >> enabled >> next_id >> size;
/* Assign this path a new id */ /* Assign this path a new id */
if (library_db.find(path) != library_db.end()) { if (library_db.find(path) != NULL) {
print("Library already contains path: %s, skipping\n", path.c_str()); print("Library already contains path: %s, skipping\n", path.c_str());
return; return;
} }
@ -487,7 +487,7 @@ void library :: add_path(const std::string &dir)
unsigned int id; unsigned int id;
if (g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) == false) if (g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) == false)
throw -E_INVAL; throw -E_INVAL;
if (library_db.find(dir) != library_db.end()) if (library_db.find(dir) != NULL)
return; return;
id = library_db.insert(library :: Library(dir, true))->id; id = library_db.insert(library :: Library(dir, true))->id;

View File

@ -85,8 +85,8 @@ void playlist :: select(const std::string &name)
const std::set<unsigned int> &playlist :: get_tracks(const std::string &name) const std::set<unsigned int> &playlist :: get_tracks(const std::string &name)
{ {
if ((name == "Banned") || (name == "Favorites")) { if ((name == "Banned") || (name == "Favorites")) {
Database<IndexEntry>::iterator it = playlist_db.find(name); IndexEntry *it = playlist_db.find(name);
if (it != playlist_db.end()) if (it != NULL)
return it->values; return it->values;
return empty_set; return empty_set;
} }

View File

@ -197,19 +197,19 @@ bool Track :: less_than(Track *rhs, sort_t field)
Track *tagdb :: add_track(const std::string &filepath, Library *library) Track *tagdb :: add_track(const std::string &filepath, Library *library)
{ {
unsigned int size = track_db.size(); unsigned int size = track_db.size();
Database<Track>::iterator it = track_db.insert(Track(filepath, library)); Track *track = track_db.insert(Track(filepath, library));
if (size == track_db.size()) if (size == track_db.size())
return NULL; return NULL;
return &(*it); return track;
} }
Library *tagdb :: add_library(const std::string &filepath) Library *tagdb :: add_library(const std::string &filepath)
{ {
unsigned int size = library_db.size(); unsigned int size = library_db.size();
Database<Library>::iterator it = library_db.insert(Library(filepath)); Library *library = library_db.insert(Library(filepath));
if (size == library_db.size()) if (size == library_db.size())
return NULL; return NULL;
return &(*it); return library;
} }
void tagdb :: remove_track(unsigned int track_id) void tagdb :: remove_track(unsigned int track_id)
@ -229,10 +229,7 @@ void tagdb :: remove_library(unsigned int library_id)
Track *tagdb :: lookup(unsigned int track_id) Track *tagdb :: lookup(unsigned int track_id)
{ {
Database<Track>::iterator it = track_db.at(track_id); return track_db.at(track_id);
if (it == track_db.end())
return NULL;
return &(*it);
} }
Database<Track> &tagdb :: get_track_db() Database<Track> &tagdb :: get_track_db()

View File

@ -156,10 +156,10 @@ int main(int argc, char **argv)
* 8. Test access by id * 8. Test access by id
*/ */
for (unsigned int i = 0; i < n + 10; i++) { for (unsigned int i = 0; i < n + 10; i++) {
Database<IntEntry>::iterator it = db.at(i); IntEntry *it = db.at(i);
if (((i % 2) == 0) && (it != db.end())) if (((i % 2) == 0) && (it != NULL))
test_results(false, __LINE__); test_results(false, __LINE__);
if ((i >= n) && (it != db.end())) if ((i >= n) && (it != NULL))
test_results(false, __LINE__); test_results(false, __LINE__);
} }
test_results(true, __LINE__); test_results(true, __LINE__);

View File

@ -46,8 +46,8 @@ int main(int argc, char **argv)
* 0: Test inserting when there is no key * 0: Test inserting when there is no key
*/ */
index.insert("a", 0); index.insert("a", 0);
Index :: iterator it = index.find("a"); IndexEntry *it = index.find("a");
if (it == index.end()) if (it == NULL)
test_results(false, __LINE__); test_results(false, __LINE__);
if (it->values.size() == 0) if (it->values.size() == 0)
test_results(false, __LINE__); test_results(false, __LINE__);

View File

@ -74,23 +74,23 @@ int main(int argc, char **argv)
/** /**
* Test adding and removing multiple tracks * Test adding and removing multiple tracks
*/ */
tagdb :: add_track("Music/1.ogg", library); Track *track1 = tagdb :: add_track("Music/1.ogg", library);
tagdb :: add_track("Music/10.ogg", library); Track *track2 = tagdb :: add_track("Music/10.ogg", library);
tagdb :: add_track("Music/15.ogg", library); Track *track3 = tagdb :: add_track("Music/15.ogg", library);
tagdb :: add_track("Music/60.ogg", library); Track *track4 = tagdb :: add_track("Music/60.ogg", library);
tagdb :: add_track("Music/90.ogg", library); Track *track5 = tagdb :: add_track("Music/90.ogg", library);
tagdb :: add_track("Music/600.ogg", library); Track *track6 = tagdb :: add_track("Music/600.ogg", library);
tagdb :: add_track("Music/666.ogg", library); Track *track7 = tagdb :: add_track("Music/666.ogg", library);
test_track_size(7, __LINE__); test_track_size(7, __LINE__);
test_results(tagdb :: lookup(0) == NULL, __LINE__); test_results(tagdb :: lookup(0) == NULL, __LINE__);
test_results(tagdb :: lookup(1)->id == 1, __LINE__); test_results(tagdb :: lookup(1) == track1, __LINE__);
test_results(tagdb :: lookup(2)->id == 2, __LINE__); test_results(tagdb :: lookup(2) == track2, __LINE__);
test_results(tagdb :: lookup(3)->id == 3, __LINE__); test_results(tagdb :: lookup(3) == track3, __LINE__);
test_results(tagdb :: lookup(4)->id == 4, __LINE__); test_results(tagdb :: lookup(4) == track4, __LINE__);
test_results(tagdb :: lookup(5)->id == 5, __LINE__); test_results(tagdb :: lookup(5) == track5, __LINE__);
test_results(tagdb :: lookup(6)->id == 6, __LINE__); test_results(tagdb :: lookup(6) == track6, __LINE__);
test_results(tagdb :: lookup(7)->id == 7, __LINE__); test_results(tagdb :: lookup(7) == track7, __LINE__);
test_results(tagdb :: lookup(8) == NULL, __LINE__); test_results(tagdb :: lookup(8) == NULL, __LINE__);