diff --git a/core/filter.cpp b/core/filter.cpp index 5d254f69..f39c3ebe 100644 --- a/core/filter.cpp +++ b/core/filter.cpp @@ -36,26 +36,28 @@ void filter_add(const gchar *text, unsigned int index) } } -void filter :: search(const std::string &text, struct set *res) +void filter_search(const gchar *text, struct set *res) { - gchar *g_lc = string_lowercase(text.c_str()); - const std::string lc = g_lc; - size_t begin = 0, end; - index_entry *found; + gchar *lower = string_lowercase(text); + struct index_entry *found; + glong begin, end; + gchar *c, *substr; - g_free(g_lc); set_clear(res); + c = lower; - for (end = 1; end <= lc.size(); end++) { - end = lc.find(' ', begin); - if (end == std::string::npos) - end = lc.size(); + for (begin = 0, end = 1; end <= g_utf8_strlen(lower, -1); end++) { + c = g_utf8_next_char(c); + if ((*c != '\0') && !g_unichar_isspace(g_utf8_get_char(c))) + continue; + + substr = g_utf8_substring(lower, begin, end); + found = INDEX_ENTRY(db_get(&filter_index, substr)); + g_free(substr); - found = INDEX_ENTRY(db_get(&filter_index, - lc.substr(begin, end- begin).c_str())); if (!found) { set_clear(res); - return; + break; } if (begin == 0) @@ -63,6 +65,9 @@ void filter :: search(const std::string &text, struct set *res) else set_inline_intersect(&found->ie_set, res); + c = g_utf8_next_char(c); begin = ++end; } + + g_free(lower); } diff --git a/gui/queue/window.cpp b/gui/queue/window.cpp index 576316cc..2e3786ee 100644 --- a/gui/queue/window.cpp +++ b/gui/queue/window.cpp @@ -36,7 +36,7 @@ void QueueWindow :: filter(std::string &text) { _q_search_empty = (text.find_first_not_of(" \t") == std::string::npos); if (!_q_search_empty) - filter :: search(text, &_q_search_res); + filter_search(text.c_str(), &_q_search_res); q_filter->refilter(); } diff --git a/include/core/filter.h b/include/core/filter.h index 7a722fd1..78d8ce8c 100644 --- a/include/core/filter.h +++ b/include/core/filter.h @@ -23,17 +23,6 @@ extern "C" { */ namespace filter { - /** - * Break the input text into lowercase words and search the Index - * for matches. The results set should be filled out with the - * intersection of the IndexEntry for each word. If any word does - * not appear in the index, then the result set should be empty. - * - * @param text The text to search for. - * @param res The results set to fill in with matching indexes. - */ - void search(const std::string &, struct set *); - /** * Converts the input text to lowercase and returns the result. * @@ -50,4 +39,7 @@ void filter_deinit(); /* Add the input string to the index. */ void filter_add(const gchar *, unsigned int); +/* Search for the input string in the index. */ +void filter_search(const gchar *, struct set *); + #endif /* OCARINA_CORE_FILTER_H */ diff --git a/tests/core/filter.cpp b/tests/core/filter.cpp index 60c7dd5c..505d78b1 100644 --- a/tests/core/filter.cpp +++ b/tests/core/filter.cpp @@ -34,35 +34,35 @@ static void test_filter() } test_loop_passed(); /* Search for a word! */ - filter :: search("hyrule", &res); + filter_search("hyrule", &res); test_equal(set_size(&res), 3); test_equal(set_has(&res, 1), (bool)true); /* hyrule symphony */ test_equal(set_has(&res, 3), (bool)true); /* hyrule field */ test_equal(set_has(&res, 4), (bool)true); /* hyrule castle */ /* A second search should clear the set. */ - filter :: search("zelda", &res); + filter_search("zelda", &res); test_equal(set_size(&res), 2); test_equal(set_has(&res, 11), (bool)true); /* princess zelda */ test_equal(set_has(&res, 13), (bool)true); /* the legend of zelda medley */ /* Partial word search. */ - filter :: search("ko", &res); + filter_search("ko", &res); test_equal(set_size(&res), 2); test_equal(set_has(&res, 0), (bool)true); /* koji kondo */ test_equal(set_has(&res, 2), (bool)true); /* kokiri forest */ /* Multiple word search. */ - filter :: search("hyrule field", &res); + filter_search("hyrule field", &res); test_equal(set_size(&res), 1); test_equal(set_has(&res, 3), (bool)true); /* hyrule field */ /* Search for unknown word. */ - filter :: search("field termina", &res); + filter_search("field termina", &res); test_equal(set_size(&res), 0); /* Search for empty string. */ - filter :: search("", &res); + filter_search("", &res); test_equal(set_size(&res), 0); filter_deinit(); diff --git a/tests/core/tags/track.cpp b/tests/core/tags/track.cpp index a40dd3b2..d2cb6939 100644 --- a/tests/core/tags/track.cpp +++ b/tests/core/tags/track.cpp @@ -144,20 +144,22 @@ static void test_track_filter() { struct set search = SET_INIT(); - filter :: search("Title Theme", &search); + filter_search("Title Theme", &search); test_equal(set_size(&search), (size_t)1); test_equal(set_has(&search, 0), true); - filter :: search("Koji Kondo", &search); + filter_search("Koji Kondo", &search); test_equal(set_size(&search), (size_t)1); test_equal(set_has(&search, 0), true); - filter :: search("Hyrule Symphony", &search); + filter_search("Hyrule Symphony", &search); test_equal(set_size(&search), (size_t)1); test_equal(set_has(&search, 0), true); - filter :: search("No Track", &search); + filter_search("No Track", &search); test_equal(set_size(&search), (size_t)0); + + set_deinit(&search); } static void test_track_compare()