2015-11-10 10:17:52 -05:00
|
|
|
/*
|
2013-08-25 10:33:48 -04:00
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
|
|
*/
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/filter.h>
|
2015-01-30 10:03:18 -05:00
|
|
|
#include <core/string.h>
|
2013-08-25 10:33:48 -04:00
|
|
|
|
2016-04-29 07:57:06 -04:00
|
|
|
static GHashTable *filter_index = NULL;
|
2013-08-25 10:33:48 -04:00
|
|
|
|
2015-09-29 16:25:16 -04:00
|
|
|
|
2016-04-29 11:10:48 -04:00
|
|
|
GHashTable *__filter_copy(GHashTable *set)
|
2016-04-29 10:17:54 -04:00
|
|
|
{
|
|
|
|
GHashTableIter iter;
|
2016-04-29 11:10:48 -04:00
|
|
|
GHashTable *res;
|
2016-04-29 10:17:54 -04:00
|
|
|
gpointer data;
|
|
|
|
|
2016-04-29 11:10:48 -04:00
|
|
|
res = g_hash_table_new(g_direct_hash, g_direct_equal);
|
|
|
|
g_hash_table_iter_init(&iter, set);
|
|
|
|
|
2016-04-29 10:17:54 -04:00
|
|
|
while (g_hash_table_iter_next(&iter, &data, NULL))
|
2016-04-29 11:10:48 -04:00
|
|
|
g_hash_table_add(res, data);
|
|
|
|
|
|
|
|
return res;
|
2016-04-29 10:17:54 -04:00
|
|
|
}
|
|
|
|
|
2016-04-29 10:35:32 -04:00
|
|
|
void __filter_inline_intersect(GHashTable *lhs, GHashTable *rhs)
|
2016-04-29 10:17:54 -04:00
|
|
|
{
|
|
|
|
GHashTableIter iter;
|
|
|
|
gpointer data;
|
|
|
|
|
2016-04-29 10:35:32 -04:00
|
|
|
g_hash_table_iter_init(&iter, rhs);
|
2016-04-29 10:17:54 -04:00
|
|
|
while (g_hash_table_iter_next(&iter, &data, NULL)) {
|
2016-04-29 10:35:32 -04:00
|
|
|
if (!g_hash_table_contains(lhs, data))
|
2016-04-29 10:17:54 -04:00
|
|
|
g_hash_table_iter_remove(&iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-29 07:57:06 -04:00
|
|
|
void filter_init()
|
|
|
|
{
|
2016-04-29 10:35:32 -04:00
|
|
|
filter_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
|
|
|
|
(GDestroyNotify)g_hash_table_destroy);
|
2016-04-29 07:57:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void filter_deinit()
|
|
|
|
{
|
|
|
|
g_hash_table_destroy(filter_index);
|
|
|
|
}
|
2013-08-25 10:33:48 -04:00
|
|
|
|
2016-04-29 09:03:20 -04:00
|
|
|
void filter_add(const gchar *text, void *data)
|
2013-08-25 10:33:48 -04:00
|
|
|
{
|
2015-11-10 09:36:38 -05:00
|
|
|
const gchar *c = g_utf8_next_char(text);
|
|
|
|
glong begin, end;
|
2016-04-29 10:35:32 -04:00
|
|
|
GHashTable *set;
|
2015-11-10 09:36:38 -05:00
|
|
|
gchar *substr;
|
2014-03-15 20:44:07 -04:00
|
|
|
|
2015-11-10 09:36:38 -05:00
|
|
|
for (begin = 0, end = 1; end <= g_utf8_strlen(text, -1); end++) {
|
|
|
|
substr = g_utf8_substring(text, begin, end);
|
2016-04-29 07:57:06 -04:00
|
|
|
set = g_hash_table_lookup(filter_index, substr);
|
|
|
|
|
|
|
|
if (!set) {
|
2016-04-29 10:35:32 -04:00
|
|
|
set = g_hash_table_new(g_direct_hash, g_direct_equal);
|
2016-04-29 07:57:06 -04:00
|
|
|
g_hash_table_insert(filter_index, substr, set);
|
|
|
|
}
|
|
|
|
|
2016-04-29 10:35:32 -04:00
|
|
|
g_hash_table_add(set, data);
|
2015-09-08 09:14:39 -04:00
|
|
|
|
2015-11-10 09:36:38 -05:00
|
|
|
if (g_unichar_isspace(g_utf8_get_char(c))) {
|
|
|
|
c = g_utf8_next_char(c);
|
2015-01-30 10:03:18 -05:00
|
|
|
begin = ++end;
|
2015-11-10 09:36:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
c = g_utf8_next_char(c);
|
2015-01-30 10:03:18 -05:00
|
|
|
}
|
2013-08-25 10:33:48 -04:00
|
|
|
}
|
|
|
|
|
2016-04-29 09:03:20 -04:00
|
|
|
void filter_remove(const gchar *text, void *data)
|
2016-04-29 08:51:58 -04:00
|
|
|
{
|
|
|
|
const gchar *c = g_utf8_next_char(text);
|
|
|
|
glong begin, end;
|
2016-04-29 10:35:32 -04:00
|
|
|
GHashTable *set;
|
2016-04-29 08:51:58 -04:00
|
|
|
gchar *substr;
|
|
|
|
|
|
|
|
for (begin = 0, end = 1; end <= g_utf8_strlen(text, -1); end++) {
|
|
|
|
substr = g_utf8_substring(text, begin, end);
|
|
|
|
set = g_hash_table_lookup(filter_index, substr);
|
|
|
|
|
|
|
|
if (set)
|
2016-04-29 10:35:32 -04:00
|
|
|
g_hash_table_remove(set, data);
|
2016-04-29 08:51:58 -04:00
|
|
|
|
|
|
|
if (g_unichar_isspace(g_utf8_get_char(c))) {
|
|
|
|
c = g_utf8_next_char(c);
|
|
|
|
begin = ++end;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = g_utf8_next_char(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 11:10:48 -04:00
|
|
|
GHashTable *filter_search(const gchar *text)
|
2013-08-25 10:33:48 -04:00
|
|
|
{
|
2015-11-10 10:12:20 -05:00
|
|
|
gchar *lower = string_lowercase(text);
|
2016-04-29 11:10:48 -04:00
|
|
|
GHashTable *found, *res = NULL;
|
2015-11-10 10:12:20 -05:00
|
|
|
glong begin, end;
|
|
|
|
gchar *c, *substr;
|
2013-08-25 10:33:48 -04:00
|
|
|
|
2015-11-10 10:12:20 -05:00
|
|
|
c = lower;
|
|
|
|
|
|
|
|
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;
|
2014-11-06 08:24:13 -05:00
|
|
|
|
2015-11-10 10:12:20 -05:00
|
|
|
substr = g_utf8_substring(lower, begin, end);
|
2016-04-29 07:57:06 -04:00
|
|
|
found = g_hash_table_lookup(filter_index, substr);
|
2015-11-10 10:12:20 -05:00
|
|
|
g_free(substr);
|
2015-01-30 10:52:15 -05:00
|
|
|
|
|
|
|
if (!found) {
|
2016-04-29 11:10:48 -04:00
|
|
|
g_hash_table_destroy(res);
|
|
|
|
res = NULL;
|
2015-11-10 10:12:20 -05:00
|
|
|
break;
|
2015-01-30 10:52:15 -05:00
|
|
|
}
|
2013-08-25 10:33:48 -04:00
|
|
|
|
2016-04-29 11:10:48 -04:00
|
|
|
if (!res)
|
|
|
|
res = __filter_copy(found);
|
2015-01-30 10:52:15 -05:00
|
|
|
else
|
2016-04-29 10:17:54 -04:00
|
|
|
__filter_inline_intersect(found, res);
|
2013-08-25 10:33:48 -04:00
|
|
|
|
2015-11-10 10:12:20 -05:00
|
|
|
c = g_utf8_next_char(c);
|
2015-01-30 10:52:15 -05:00
|
|
|
begin = ++end;
|
|
|
|
}
|
2015-11-10 10:12:20 -05:00
|
|
|
|
|
|
|
g_free(lower);
|
2016-04-29 11:10:48 -04:00
|
|
|
return res;
|
2013-08-25 10:33:48 -04:00
|
|
|
}
|