libsaria: Add filtering to the new index

Otherwise it's useless.  I search all three indexes and use the union of
those results to determine what is visible.
This commit is contained in:
Bryan Schumaker 2011-12-27 22:30:38 -05:00
parent 9c749e4ade
commit 83488dfa06
5 changed files with 138 additions and 4 deletions

View File

@ -10,6 +10,10 @@ namespace libsaria
{
void add_track(libsaria::Track &);
void filter(string &);
bool is_visible(sid_t &);
bool is_filtered();
unsigned int size();
void print_stats();
}; /* Namespace: index */

115
libsaria/index/filter.cpp Normal file
View File

@ -0,0 +1,115 @@
#include <libsaria/index.h>
#include <libsaria/format.h>
#include <libsaria/callback.h>
#include "index.h"
static set<sid_t> results;
static bool filtered = false;
/*
* Thanks to: http://stackoverflow.com/questions/1773526/in-place-c-set-intersection
* for the set intersection algorithm!
*/
static void inplace_intersect(set<sid_t> *ids)
{
set<sid_t>::iterator it1 = results.begin();
set<sid_t>::iterator it2 = ids->begin();
while ( (it1 != results.end()) && (it2 != ids->end()) ) {
if (*it1 < *it2)
results.erase(it1++);
else if (*it2 < *it1)
it2++;
else { /* *it1 == *it2 */
it1++;
it2++;
}
}
/* Remove everything in results that wasn't in inodes */
results.erase(it1, results.end());
}
static inline void search_index(string &term,
map<string, set<sid_t> > *index,
set<ino_t> *found)
{
map<string, set<sid_t> >::iterator it;
it = index->find(term);
if (it != index->end())
found->insert(it->second.begin(), it->second.end());
}
static inline void search_indexes(string &term, set<ino_t> *found)
{
search_index(term, &artist_index, found);
search_index(term, &album_index, found);
search_index(term, &title_index, found);
}
static void do_filter(list<string> *terms)
{
set<ino_t> found;
list<string>::iterator it;
for (it = terms->begin(); it != terms->end(); it++) {
found.clear();
search_indexes(*it, &found);
/*
* Key not found means we don't need to filter anymore
* just clear the results set and return.
*/
if (found.size() == 0) {
results.clear();
return;
}
/*
* This is the first result, so the result set is empty.
* Taking an intersection will always give us an empty set.
*/
if (it == terms->begin())
results = found;
else
inplace_intersect(&found);
}
}
namespace libsaria
{
void index::filter(string &search)
{
list<string> *terms = format_text(search);
results.clear();
if (terms->size() == 0)
filtered = false;
else {
do_filter(terms);
filtered = true;
}
trigger_callback(REFILTER);
}
bool index::is_visible(sid_t &songid)
{
set<sid_t>::iterator it;
if (filtered == false)
return true;
it = results.find(songid);
return it != results.end();
}
bool index::is_filtered()
{
return filtered;
}
unsigned int index::size()
{
return results.size();
}
};

View File

@ -2,6 +2,7 @@
#include <libsaria/track.h>
#include <libsaria/index.h>
#include <libsaria/format.h>
#include "index.h"
#include <map>
#include <set>

13
libsaria/index/index.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef LIBSARIA_INDEX_INTERNAL_H
#define LIBSARIA_INDEX_INTERNAL_H
#include <map>
#include <set>
#include <string>
using namespace std;
extern map<string, set<sid_t> > artist_index;
extern map<string, set<sid_t> > album_index;
extern map<string, set<sid_t> > title_index;
#endif /* LIBSARIA_INDEX_INTERNAL_H */

View File

@ -6,6 +6,7 @@ using namespace std;
#include <libsaria/audio.h>
#include <libsaria/prefs.h>
#include <libsaria/index.h>
#include <libsaria/print.h>
#include "library.h"
@ -91,7 +92,7 @@ static void print_cur_track()
static void random_next()
{
cur_track = play_list.begin();
if (libsaria::library::is_filtered()) {
if (libsaria::index::is_filtered()) {
println("Picking random track from index");
sid_t inode = libsaria::library::index_rand();
libsaria::library::play_id(inode);
@ -112,7 +113,7 @@ static void sequential_next()
if (cur_track == play_list.end())
cur_track = play_list.begin();
inode = (*cur_track)->get_songid();
} while (!libsaria::library::is_visible(inode));
} while (!libsaria::index::is_visible(inode));
}
static void pick_next()
@ -197,8 +198,8 @@ namespace libsaria
unsigned int library::size()
{
if (is_filtered() == true)
return filter_size();
if (index::is_filtered() == true)
return index::size();
return play_list.size();
}