/* * Copyright 2013 (c) Anna Schumaker. */ #include #include static GHashTable *filter_index = NULL; void __filter_copy(GHashTable *lhs, GHashTable *rhs) { GHashTableIter iter; gpointer data; g_hash_table_iter_init(&iter, lhs); while (g_hash_table_iter_next(&iter, &data, NULL)) g_hash_table_add(rhs, data); } void __filter_inline_intersect(GHashTable *lhs, GHashTable *rhs) { GHashTableIter iter; gpointer data; g_hash_table_iter_init(&iter, rhs); while (g_hash_table_iter_next(&iter, &data, NULL)) { if (!g_hash_table_contains(lhs, data)) g_hash_table_iter_remove(&iter); } } void filter_init() { filter_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy); } void filter_deinit() { g_hash_table_destroy(filter_index); } void filter_add(const gchar *text, void *data) { const gchar *c = g_utf8_next_char(text); glong begin, end; GHashTable *set; 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) { set = g_hash_table_new(g_direct_hash, g_direct_equal); g_hash_table_insert(filter_index, substr, set); } g_hash_table_add(set, data); if (g_unichar_isspace(g_utf8_get_char(c))) { c = g_utf8_next_char(c); begin = ++end; } c = g_utf8_next_char(c); } } void filter_remove(const gchar *text, void *data) { const gchar *c = g_utf8_next_char(text); glong begin, end; GHashTable *set; 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) g_hash_table_remove(set, data); if (g_unichar_isspace(g_utf8_get_char(c))) { c = g_utf8_next_char(c); begin = ++end; } c = g_utf8_next_char(c); } } void filter_search(const gchar *text, GHashTable *res) { gchar *lower = string_lowercase(text); GHashTable *found; glong begin, end; gchar *c, *substr; g_hash_table_remove_all(res); 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; substr = g_utf8_substring(lower, begin, end); found = g_hash_table_lookup(filter_index, substr); g_free(substr); if (!found) { g_hash_table_remove_all(res); break; } if (begin == 0) __filter_copy(found, res); else __filter_inline_intersect(found, res); c = g_utf8_next_char(c); begin = ++end; } g_free(lower); }