libsaria: Perform filtering

I use an in-place set intersection to find a set of songs that match the
search terms.
This commit is contained in:
Bryan Schumaker 2011-11-13 11:29:41 -05:00
parent 048313c681
commit 824f589ff2
1 changed files with 64 additions and 3 deletions

View File

@ -1,12 +1,15 @@
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#include <libsaria/format.h>
#include "library.h"
static map<string, set<ino_t> > substr_index;
static set<ino_t> results;
static bool filtered;
static void add_to_index(ino_t &inode, string &key)
{
@ -82,6 +85,59 @@ static void reindex_path(list<TrackTag> *tag_list)
task->queue();
}
/*
* Thanks to: http://stackoverflow.com/questions/1773526/in-place-c-set-intersection
* for the set intersection algorithm!
*/
static void inplace_intersect(set<ino_t> *inodes)
{
set<ino_t>::iterator it1 = results.begin();
set<ino_t>::iterator it2 = inodes->begin();
while ( (it1 != results.end()) && (it2 != inodes->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 void do_filter(list<string> &terms)
{
list<string>::iterator it;
map<string, set<ino_t> >::iterator index_iter;
for (it = terms.begin(); it != terms.end(); it++) {
index_iter = substr_index.find(*it);
/*
* Key not found means we don't need to filter anymore
* just clear the results set and return
*/
if (index_iter == substr_index.end()) {
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 = index_iter->second;
else
inplace_intersect(&index_iter->second);
}
}
namespace libsaria
{
@ -97,11 +153,16 @@ namespace libsaria
void library::filter(string &text)
{
list<string> key_list;
list<string>::iterator it;
format_text(text, key_list);
for (it = key_list.begin(); it != key_list.end(); it++)
println(*it);
results.clear();
if (key_list.size() == 0)
filtered = false;
else {
do_filter(key_list);
filtered = true;
}
}
}; /* Namespace: libsaria */