core/index: Replace index_entry iterators with struct set_iter

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-10-21 15:57:21 -04:00
parent a8bb7ffccd
commit 45207ebd2e
12 changed files with 100 additions and 110 deletions

View File

@ -34,17 +34,7 @@ const std::string filter :: add(const std::string &text, unsigned int index)
return lc; return lc;
} }
static void do_set_intersection(index_entry *entry, void filter :: search(const std::string &text, struct set *res)
std::set<unsigned int> &res)
{
std::set<unsigned int> tmp;
set_intersection(entry->begin(), entry->end(), res.begin(), res.end(),
std::inserter(tmp, tmp.begin()));
res.swap(tmp);
}
void filter :: search(const std::string &text, std::set<unsigned int> &res)
{ {
gchar *g_lc = string_lowercase(text.c_str()); gchar *g_lc = string_lowercase(text.c_str());
const std::string lc = g_lc; const std::string lc = g_lc;
@ -52,7 +42,7 @@ void filter :: search(const std::string &text, std::set<unsigned int> &res)
index_entry *found; index_entry *found;
g_free(g_lc); g_free(g_lc);
res.clear(); set_clear(res);
for (end = 1; end <= lc.size(); end++) { for (end = 1; end <= lc.size(); end++) {
end = lc.find(' ', begin); end = lc.find(' ', begin);
@ -61,15 +51,14 @@ void filter :: search(const std::string &text, std::set<unsigned int> &res)
found = db_get(&filter_index, lc.substr(begin, end- begin).c_str()); found = db_get(&filter_index, lc.substr(begin, end- begin).c_str());
if (!found) { if (!found) {
res.clear(); set_clear(res);
return; return;
} }
if (begin == 0) if (begin == 0)
std::copy(found->begin(), found->end(), set_copy(&found->ie_set, res);
std::inserter(res, res.begin()));
else else
do_set_intersection(found, res); set_inline_intersect(&found->ie_set, res);
begin = ++end; begin = ++end;
} }

View File

@ -4,47 +4,41 @@
#include <core/index.h> #include <core/index.h>
index_entry :: index_entry() {} index_entry :: index_entry()
{
ie_set = SET_INIT();
}
index_entry :: index_entry(const std::string &key) index_entry :: index_entry(const std::string &key)
: ie_key(key) : ie_key(key)
{} {
ie_set = SET_INIT();
}
index_entry :: ~index_entry()
{
set_deinit(&ie_set);
}
const std::string index_entry :: primary_key() const const std::string index_entry :: primary_key() const
{ {
return ie_key; return ie_key;
} }
typename index_entry::iterator index_entry :: begin()
{
return ie_set.begin();
}
typename index_entry::iterator index_entry :: end()
{
return ie_set.end();
}
void index_entry :: write(file &file) void index_entry :: write(file &file)
{ {
std::set<unsigned int>::iterator it; file_writef(&file, "%s\n" , ie_key.c_str());
file_writef(&file, "%s\n%zu ", ie_key.c_str(), ie_set.size()); set_write(&file, &ie_set);
for (it = ie_set.begin(); it != ie_set.end(); it++)
file_writef(&file, "%u ", *it);
} }
void index_entry :: read(file &file) void index_entry :: read(file &file)
{ {
unsigned int num, val;
gchar *key = file_readl(&file); gchar *key = file_readl(&file);
file_readf(&file, "%u ", &num);
ie_key = key; ie_key = key;
g_free(key); g_free(key);
for (unsigned int i = 0; i < num; i++) { set_read(&file, &ie_set);
file_readf(&file, "%u", &val);
ie_set.insert(val);
}
} }
@ -60,7 +54,7 @@ index_entry *index_insert(database<index_entry> *index, const gchar *key,
{ {
index_entry *it = db_find(index, key); index_entry *it = db_find(index, key);
it->ie_set.insert(value); set_insert(&it->ie_set, value);
db_autosave(index); db_autosave(index);
return it; return it;
} }
@ -70,7 +64,7 @@ void index_remove(database<index_entry> *index, const gchar *key,
{ {
index_entry *it = db_get(index, key); index_entry *it = db_get(index, key);
if (it) { if (it) {
it->ie_set.erase(value); set_remove(&it->ie_set, value);
db_autosave(index); db_autosave(index);
} }
} }
@ -81,5 +75,5 @@ bool index_has(database<index_entry> *index, const gchar *key, unsigned int valu
if (!it) if (!it)
return false; return false;
return it->ie_set.find(value) != it->ie_set.end(); return set_has(&it->ie_set, value);
} }

View File

@ -24,11 +24,11 @@ public:
void fill(index_entry *ent) void fill(index_entry *ent)
{ {
std::set<unsigned int>::iterator it; struct set_iter it;
clear(); clear();
for (it = ent->begin(); it != ent->end(); it++) set_for_each(&ent->ie_set, &it)
add(tags :: get_track(*it)); add(tags :: get_track(it.it_val));
} }
unsigned int find_average_count() unsigned int find_average_count()
@ -85,7 +85,7 @@ static std::string cur_plist;
void playlist :: init() void playlist :: init()
{ {
std::set<unsigned int>::iterator it; struct set_iter it;
index_init(&playlist_db, "playlist.db", true); index_init(&playlist_db, "playlist.db", true);
db_load(&playlist_db); db_load(&playlist_db);
@ -94,8 +94,8 @@ void playlist :: init()
if (!ent) if (!ent)
return; return;
for (it = ent->begin(); it != ent->end(); it++) set_for_each(&ent->ie_set, &it)
library :: get_queue()->del(tags :: get_track(*it)); library :: get_queue()->del(tags :: get_track(it.it_val));
} }
bool playlist :: has(Track *track, const std::string &name) bool playlist :: has(Track *track, const std::string &name)

View File

@ -88,14 +88,14 @@ void update_paths()
static void remove_banned_tracks() static void remove_banned_tracks()
{ {
std::set<unsigned int>::iterator it;
index_entry *ent = playlist :: get_tracks("Banned"); index_entry *ent = playlist :: get_tracks("Banned");
struct set_iter it;
if (!ent) if (!ent)
return; return;
for (it = ent->begin(); it != ent->end(); it++) set_for_each(&ent->ie_set, &it)
library :: get_queue()->del(tags :: get_track(*it)); library :: get_queue()->del(tags :: get_track(it.it_val));
} }

View File

@ -8,11 +8,13 @@ QueueWindow :: QueueWindow(BaseObjectType *cobject,
const Glib::RefPtr<Gtk::Builder> builder) const Glib::RefPtr<Gtk::Builder> builder)
: Gtk::ScrolledWindow(cobject), _builder(builder), _q_search_empty(true) : Gtk::ScrolledWindow(cobject), _builder(builder), _q_search_empty(true)
{ {
_q_search_res = SET_INIT();
_builder->get_widget("q_treeview", q_treeview); _builder->get_widget("q_treeview", q_treeview);
} }
QueueWindow :: ~QueueWindow() QueueWindow :: ~QueueWindow()
{ {
set_deinit(&_q_search_res);
} }
void QueueWindow :: init(Queue *queue) void QueueWindow :: init(Queue *queue)
@ -32,21 +34,19 @@ void QueueWindow :: filter(std::string &text)
{ {
_q_search_empty = (text.find_first_not_of(" \t") == std::string::npos); _q_search_empty = (text.find_first_not_of(" \t") == std::string::npos);
if (!_q_search_empty) if (!_q_search_empty)
filter :: search(text, _q_search_res); filter :: search(text, &_q_search_res);
q_filter->refilter(); q_filter->refilter();
} }
bool QueueWindow :: filter_ids(const Gtk::TreeIter &iter) bool QueueWindow :: filter_ids(const Gtk::TreeIter &iter)
{ {
unsigned int id; unsigned int id;
std::set<unsigned int>::iterator it;
if (_q_search_empty) if (_q_search_empty)
return true; return true;
id = q_model->iter_to_id(iter); id = q_model->iter_to_id(iter);
it = _q_search_res.find(_queue->operator[](id)->index()); return set_has(&_q_search_res, _queue->operator[](id)->index());
return it != _q_search_res.end();
} }
void QueueWindow :: on_row_activated(const Gtk::TreePath &path, void QueueWindow :: on_row_activated(const Gtk::TreePath &path,

View File

@ -4,7 +4,10 @@
#ifndef OCARINA_CORE_FILTER_H #ifndef OCARINA_CORE_FILTER_H
#define OCARINA_CORE_FILTER_H #define OCARINA_CORE_FILTER_H
#include <set> extern "C" {
#include <core/set.h>
}
#include <string> #include <string>
/** /**
@ -45,7 +48,7 @@ namespace filter {
* @param text The text to search for. * @param text The text to search for.
* @param res The results set to fill in with matching indexes. * @param res The results set to fill in with matching indexes.
*/ */
void search(const std::string &, std::set<unsigned int> &); void search(const std::string &, struct set *);
/** /**
* Converts the input text to lowercase and returns the result. * Converts the input text to lowercase and returns the result.

View File

@ -5,8 +5,10 @@
#define OCARINA_CORE_INDEX_H #define OCARINA_CORE_INDEX_H
#include <core/database.h> #include <core/database.h>
extern "C" {
#include <core/set.h>
}
#include <set>
#include <string> #include <string>
@ -15,13 +17,8 @@
* integer identifiers. This lets us use a Database as an inverted index. * integer identifiers. This lets us use a Database as an inverted index.
*/ */
struct index_entry : public DatabaseEntry { struct index_entry : public DatabaseEntry {
std::string ie_key; std::string ie_key;
std::set<unsigned int> ie_set; struct set ie_set;
/** Iterator access for our backing std::set */
typedef typename std::set<unsigned int>::iterator iterator;
/** Const iterator access for our backing std::set */
typedef typename std::set<unsigned int>::const_iterator const_iterator;
index_entry(); /**< Create an empty IndexEntry. */ index_entry(); /**< Create an empty IndexEntry. */
@ -31,6 +28,7 @@ struct index_entry : public DatabaseEntry {
* @param key The key associated with this IndexEntry. * @param key The key associated with this IndexEntry.
*/ */
index_entry(const std::string &); index_entry(const std::string &);
~index_entry();
/** /**
@ -40,17 +38,6 @@ struct index_entry : public DatabaseEntry {
*/ */
const std::string primary_key() const; const std::string primary_key() const;
/**
* @return An iterator pointing to the first item in IndexEntry::_values
*/
iterator begin();
/**
* @return An iterator pointing past the last item in IndexEntry::_vaues
*/
iterator end();
/** /**
* Write an IndexEntry to file. * Write an IndexEntry to file.
* *

View File

@ -4,16 +4,18 @@
#ifndef OCARINA_GUI_QUEUE_WINDOW_H #ifndef OCARINA_GUI_QUEUE_WINDOW_H
#define OCARINA_GUI_QUEUE_WINDOW_H #define OCARINA_GUI_QUEUE_WINDOW_H
extern "C" {
#include <core/set.h>
}
#include <gui/queue/model.h> #include <gui/queue/model.h>
#include <gtkmm.h> #include <gtkmm.h>
#include <set>
class QueueWindow : public Gtk::ScrolledWindow { class QueueWindow : public Gtk::ScrolledWindow {
private: private:
Glib::RefPtr<Gtk::Builder> _builder; Glib::RefPtr<Gtk::Builder> _builder;
Queue *_queue; Queue *_queue;
std::set<unsigned int> _q_search_res; struct set _q_search_res;
bool _q_search_empty; bool _q_search_empty;
public: public:

View File

@ -47,17 +47,18 @@ static void test_addition()
static void do_test_search(const std::string &text, unsigned int len, static void do_test_search(const std::string &text, unsigned int len,
unsigned int *ids) unsigned int *ids)
{ {
int init_values[] = { 1, 2, 3, 4, 5 }; struct set res = SET_INIT();
std::set<unsigned int> res(init_values, init_values + 5); unsigned int i = 0;
std::set<unsigned int>::iterator it;
filter :: search(text, res); for (unsigned int i = 1; i <= 6; i++)
test_equal(res.size(), (size_t)len); set_insert(&res, i);
it = res.begin(); filter :: search(text, &res);
for (unsigned int i = 0; i < len; i++) test_equal(set_size(&res), (size_t)len);
test_loop_equal(*it++, ids[i], i);
test_loop_passed(); for (i = 0; i < len; i++) {
test_loop_equal(set_has(&res, ids[i]), true, i);
} test_loop_passed();
} }
static void test_search() static void test_search()

View File

@ -9,12 +9,20 @@
static void test_entry() static void test_entry()
{ {
index_entry *ie = new index_entry("Link"); index_entry *ie = new index_entry("Link");
struct set_iter it;
unsigned int i;
struct file f; struct file f;
test_equal(ie->primary_key(), "Link"); test_equal(ie->primary_key(), "Link");
ie->ie_set.insert(0); set_insert(&ie->ie_set, 0);
ie->ie_set.insert(1); set_insert(&ie->ie_set, 1);
ie->ie_set.insert(2); set_insert(&ie->ie_set, 2);
i = 0;
set_for_each(&ie->ie_set, &it) {
test_loop_equal(it.it_val, i, i);
i++;
} test_loop_passed();
file_init(&f, "index_entry", 0); file_init(&f, "index_entry", 0);
file_open(&f, OPEN_WRITE); file_open(&f, OPEN_WRITE);
@ -25,18 +33,24 @@ static void test_entry()
ie = new index_entry(); ie = new index_entry();
test_equal(ie->primary_key(), ""); test_equal(ie->primary_key(), "");
test_equal(ie->ie_set.size(), 0); test_equal(set_size(&ie->ie_set), 0);
file_open(&f, OPEN_READ); file_open(&f, OPEN_READ);
ie->read(f); ie->read(f);
test_equal(ie->primary_key(), "Zelda"); test_equal(ie->primary_key(), "Zelda");
test_equal(ie->ie_set.size(), 0); test_equal(set_size(&ie->ie_set), 0);
ie->read(f); ie->read(f);
test_equal(ie->primary_key(), "Link"); test_equal(ie->primary_key(), "Link");
test_equal(ie->ie_set.size(), 3); test_equal(set_size(&ie->ie_set), 3);
file_close(&f); file_close(&f);
i = 0;
set_for_each(&ie->ie_set, &it) {
test_loop_equal(it.it_val, i, i);
i++;
} test_loop_passed();
delete ie; delete ie;
} }
@ -59,7 +73,7 @@ static void test_stress(unsigned int N)
for (i = 0; i < N; i++) for (i = 0; i < N; i++)
ie2 = index_insert(&index, key.c_str(), i); ie2 = index_insert(&index, key.c_str(), i);
test_loop_equal(ie, ie2, c - 'a'); test_loop_equal(ie, ie2, c - 'a');
test_loop_equal(ie->ie_set.size(), N, c - 'a'); test_loop_equal(set_size(&ie->ie_set), N, c - 'a');
test_loop_equal(index.db_size, c - 'a' + 1, c - 'a'); test_loop_equal(index.db_size, c - 'a' + 1, c - 'a');
} test_loop_passed(); } test_loop_passed();
test_equal(index.db_size, 26); test_equal(index.db_size, 26);
@ -79,7 +93,7 @@ static void test_stress(unsigned int N)
index_remove(&index, key.c_str(), i); index_remove(&index, key.c_str(), i);
ie = db_find(&index, key.c_str()); ie = db_find(&index, key.c_str());
test_loop_not_equal(ie, NULL, c - 'a'); test_loop_not_equal(ie, NULL, c - 'a');
test_loop_equal(ie->ie_set.size(), 0, c - 'a'); test_loop_equal(set_size(&ie->ie_set), 0, c - 'a');
} test_loop_passed(); } test_loop_passed();
index_remove(&index, "ZZ", 42); index_remove(&index, "ZZ", 42);
test_equal(index.db_size, 26); test_equal(index.db_size, 26);

View File

@ -30,10 +30,10 @@ static void test_init()
playlist :: init(); playlist :: init();
ent = playlist :: get_tracks("Banned"); ent = playlist :: get_tracks("Banned");
test_equal(ent->ie_set.size(), (size_t)4); test_equal(set_size(&ent->ie_set), (size_t)4);
test_equal(library :: get_queue()->size(), (unsigned)20); test_equal(library :: get_queue()->size(), (unsigned)20);
ent = playlist :: get_tracks("Favorites"); ent = playlist :: get_tracks("Favorites");
test_equal(ent->ie_set.size(), (size_t)8); test_equal(set_size(&ent->ie_set), (size_t)8);
ent = playlist :: get_tracks("No Such Playlist"); ent = playlist :: get_tracks("No Such Playlist");
test_equal(ent, IDX_NULL); test_equal(ent, IDX_NULL);
} }
@ -68,14 +68,14 @@ static void test_add()
playlist :: add(tags :: get_track(5), "Banned"); playlist :: add(tags :: get_track(5), "Banned");
ent = playlist :: get_tracks("Banned"); ent = playlist :: get_tracks("Banned");
test_equal(ent->ie_set.size(), (size_t)5); test_equal(set_size(&ent->ie_set), (size_t)5);
test_equal(q->size(), (unsigned)8); test_equal(q->size(), (unsigned)8);
test_equal(l->size(), (unsigned)19); test_equal(l->size(), (unsigned)19);
playlist :: add(tags :: get_track(16), "Favorites"); playlist :: add(tags :: get_track(16), "Favorites");
playlist :: add(tags :: get_track(5), "Favorites"); playlist :: add(tags :: get_track(5), "Favorites");
ent = playlist :: get_tracks("Favorites"); ent = playlist :: get_tracks("Favorites");
test_equal(ent->ie_set.size(), (size_t)9); test_equal(set_size(&ent->ie_set), (size_t)9);
test_equal(q->size(), (unsigned)9); test_equal(q->size(), (unsigned)9);
playlist :: add(tags :: get_track(6), "No Playlist"); playlist :: add(tags :: get_track(6), "No Playlist");
@ -90,13 +90,13 @@ static void test_delete()
playlist :: del(tags :: get_track(5), "Banned"); playlist :: del(tags :: get_track(5), "Banned");
ent = playlist :: get_tracks("Banned"); ent = playlist :: get_tracks("Banned");
test_equal(ent->ie_set.size(), (size_t)4); test_equal(set_size(&ent->ie_set), (size_t)4);
test_equal(q->size(), (unsigned)9); test_equal(q->size(), (unsigned)9);
test_equal(l->size(), (unsigned)20); test_equal(l->size(), (unsigned)20);
playlist :: del(tags :: get_track(5), "Favorites"); playlist :: del(tags :: get_track(5), "Favorites");
ent = playlist :: get_tracks("Favorites"); ent = playlist :: get_tracks("Favorites");
test_equal(ent->ie_set.size(), (size_t)8); test_equal(set_size(&ent->ie_set), (size_t)8);
test_equal(q->size(), (unsigned)8); test_equal(q->size(), (unsigned)8);
playlist :: del(tags :: get_track(6), "No Playlist"); playlist :: del(tags :: get_track(6), "No Playlist");

View File

@ -73,7 +73,7 @@ static void test_track_tag_constructor()
Track a(album, artist, genre, library, Track a(album, artist, genre, library,
"Hyrule Symphony/13 - Legend of Zelda Medley.mp3", "Hyrule Symphony/13 - Legend of Zelda Medley.mp3",
"Legend of Zelda Medley", 288, 13); "Legend of Zelda Medley", 288, 13);
std::set<unsigned int> search; struct set search = SET_INIT();
Track b; Track b;
verify_track_tag(&a, 1); verify_track_tag(&a, 1);
@ -90,17 +90,17 @@ static void test_track_tag_constructor()
verify_track_tag(&b, 2); verify_track_tag(&b, 2);
filter :: search("Legend of Zelda Medley", search); filter :: search("Legend of Zelda Medley", &search);
test_equal(search.size(), (size_t)1); test_equal(set_size(&search), (size_t)1);
test_equal((*search.begin()), (unsigned)0); test_equal(set_has(&search, 0), true);
filter :: search("Koji Kondo", search); filter :: search("Koji Kondo", &search);
test_equal(search.size(), (size_t)1); test_equal(set_size(&search), (size_t)1);
test_equal((*search.begin()), (unsigned)0); test_equal(set_has(&search, 0), true);
filter :: search("Hyrule Symphony", search); filter :: search("Hyrule Symphony", &search);
test_equal(search.size(), (size_t)1); test_equal(set_size(&search), (size_t)1);
test_equal((*search.begin()), (unsigned)0); test_equal(set_has(&search, 0), true);
} }
static void test_track_tag_destructor() static void test_track_tag_destructor()