From 83488dfa06f5a74d2db7dd4017453fcfd20d0695 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 27 Dec 2011 22:30:38 -0500 Subject: [PATCH] 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. --- include/libsaria/index.h | 4 ++ libsaria/index/filter.cpp | 115 ++++++++++++++++++++++++++++++++++++++ libsaria/index/index.cpp | 1 + libsaria/index/index.h | 13 +++++ libsaria/library/list.cpp | 9 +-- 5 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 libsaria/index/filter.cpp create mode 100644 libsaria/index/index.h diff --git a/include/libsaria/index.h b/include/libsaria/index.h index fd516b79..1675bb8b 100644 --- a/include/libsaria/index.h +++ b/include/libsaria/index.h @@ -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 */ diff --git a/libsaria/index/filter.cpp b/libsaria/index/filter.cpp new file mode 100644 index 00000000..fe53d8aa --- /dev/null +++ b/libsaria/index/filter.cpp @@ -0,0 +1,115 @@ + +#include +#include +#include +#include "index.h" + +static set 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 *ids) +{ + set::iterator it1 = results.begin(); + set::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 > *index, + set *found) +{ + map >::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 *found) +{ + search_index(term, &artist_index, found); + search_index(term, &album_index, found); + search_index(term, &title_index, found); +} + +static void do_filter(list *terms) +{ + set found; + list::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 *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::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(); + } +}; diff --git a/libsaria/index/index.cpp b/libsaria/index/index.cpp index 74d52edf..e8f7cd5f 100644 --- a/libsaria/index/index.cpp +++ b/libsaria/index/index.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "index.h" #include #include diff --git a/libsaria/index/index.h b/libsaria/index/index.h new file mode 100644 index 00000000..6963ecbc --- /dev/null +++ b/libsaria/index/index.h @@ -0,0 +1,13 @@ +#ifndef LIBSARIA_INDEX_INTERNAL_H +#define LIBSARIA_INDEX_INTERNAL_H + +#include +#include +#include +using namespace std; + +extern map > artist_index; +extern map > album_index; +extern map > title_index; + +#endif /* LIBSARIA_INDEX_INTERNAL_H */ diff --git a/libsaria/library/list.cpp b/libsaria/library/list.cpp index 1ba2c664..08cf4417 100644 --- a/libsaria/library/list.cpp +++ b/libsaria/library/list.cpp @@ -6,6 +6,7 @@ using namespace std; #include #include +#include #include #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(); }