summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Kang <jonathan121537@gmail.com>2015-08-11 13:29:55 +0200
committerJonathan Kang <jonathan121537@gmail.com>2015-08-11 13:29:55 +0200
commite73c75620fe51a6a45469697ed2c8ee9e5354bad (patch)
tree1d7b168ba26725aabdb14e9cf795e591548eb58a
parent3d58b10bfd87c373136be10f265a45d771a18270 (diff)
downloadgnome-logs-e73c75620fe51a6a45469697ed2c8ee9e5354bad.tar.gz
Improve search by using boolean combinations
https://bugzilla.gnome.org/show_bug.cgi?id=709152
-rw-r--r--src/gl-eventviewlist.c311
1 files changed, 243 insertions, 68 deletions
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index 2104fd5..8112c54 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -54,6 +54,12 @@ typedef struct
const gchar *boot_match;
} GlEventViewListPrivate;
+typedef enum
+{
+ LOGICAL_OR = 2,
+ LOGICAL_AND = 3
+} GlEventViewListLogic;
+
G_DEFINE_TYPE_WITH_PRIVATE (GlEventViewList, gl_event_view_list, GTK_TYPE_BOX)
static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface";
@@ -86,69 +92,270 @@ gl_event_view_search_is_case_sensitive (GlEventViewList *view)
}
static gboolean
-search_in_result (GlJournalEntry *entry,
- const gchar *search_text)
+utf8_strcasestr (const gchar *potential_hit,
+ const gchar *search_term)
+{
+ gchar *folded;
+ gboolean matches;
+
+ folded = g_utf8_casefold (potential_hit, -1);
+ matches = strstr (folded, search_term) != NULL;
+
+ g_free (folded);
+ return matches;
+}
+
+static GPtrArray *
+tokenize_search_string (gchar *search_text)
{
gchar *field_name;
gchar *field_value;
- gchar *search_text_copy;
+ GPtrArray *token_array;
+ GScanner *scanner;
+
+ token_array = g_ptr_array_new_with_free_func (g_free);
+ scanner = g_scanner_new (NULL);
+ scanner->config->cset_skip_characters = " =\t\n";
+ g_scanner_input_text (scanner, search_text, strlen (search_text));
+
+ do
+ {
+ g_scanner_get_next_token (scanner);
+ if (scanner->value.v_identifier == NULL && scanner->token != '+')
+ {
+ break;
+ }
+
+ if (scanner->token == '+')
+ {
+ g_ptr_array_add (token_array, g_strdup ("+"));
+
+ g_scanner_get_next_token (scanner);
+ if (scanner->value.v_identifier != NULL)
+ {
+ field_name = g_strdup (scanner->value.v_identifier);
+ g_ptr_array_add (token_array, field_name);
+ }
+ else
+ {
+ field_name = NULL;
+ }
+ }
+ else
+ {
+ if (token_array->len != 0)
+ {
+ g_ptr_array_add (token_array, g_strdup (" "));
+ }
+
+ field_name = g_strdup (scanner->value.v_identifier);
+ g_ptr_array_add (token_array, field_name);
+ }
+
+ g_scanner_get_next_token (scanner);
+ if (scanner->value.v_identifier != NULL)
+ {
+ field_value = g_strdup (scanner->value.v_identifier);
+ g_ptr_array_add (token_array, field_value);
+ }
+ else
+ {
+ field_value = NULL;
+ }
+ } while (field_name != NULL && field_value != NULL);
+
+ g_scanner_destroy (scanner);
+
+ return token_array;
+}
+
+static gboolean
+calculate_match (GlJournalEntry *entry,
+ GPtrArray *token_array,
+ gboolean case_sensetive)
+{
const gchar *comm;
const gchar *message;
const gchar *kernel_device;
const gchar *audit_session;
+ gboolean matches;
+ gchar *field_name;
+ gchar *field_value;
+ gint i;
+ gint match_stack[10];
+ gint match_count = 0;
+ gint token_index = 0;
comm = gl_journal_entry_get_command_line (entry);
message = gl_journal_entry_get_message (entry);
kernel_device = gl_journal_entry_get_kernel_device (entry);
audit_session = gl_journal_entry_get_audit_session (entry);
- search_text_copy = g_strdup (search_text);
- field_name = strtok (search_text_copy, "=");
- field_value = strtok (NULL, " ");
-
- if (field_value == NULL)
+ if (token_array->len == 1 && case_sensetive == TRUE)
{
+ gchar *search_text;
+
+ search_text = g_ptr_array_index (token_array, 0);
+
if ((comm ? strstr (comm, search_text) : NULL)
|| (message ? strstr (message, search_text) : NULL)
|| (kernel_device ? strstr (kernel_device, search_text) : NULL)
|| (audit_session ? strstr (audit_session, search_text) : NULL))
{
- g_free (search_text_copy);
-
return TRUE;
}
+ else
+ {
+ return FALSE;
+ }
}
- else if ((strstr ("_COMM", field_name) &&
- comm ? strstr (comm, field_value) : NULL) ||
- (strstr ("_MESSAGE", field_name) &&
- message ? strstr (message, field_value) : NULL) ||
- (strstr ("_KERNEL_DEVICE", field_name) &&
- kernel_device ? strstr (kernel_device, field_value) : NULL) ||
- (strstr ("_AUDIT_SESSION", field_name) &&
- audit_session ? strstr (audit_session, field_value) : NULL))
+ else if (token_array->len == 1 && case_sensetive == FALSE)
{
- g_free (search_text_copy);
+ gchar *search_text;
- return TRUE;
+ search_text = g_ptr_array_index (token_array, 0);
+
+ matches = (comm && utf8_strcasestr (comm, search_text)) ||
+ (message && utf8_strcasestr (message, search_text)) ||
+ (kernel_device && utf8_strcasestr (kernel_device, search_text)) ||
+ (audit_session && utf8_strcasestr (audit_session, search_text));
+
+ return matches;
}
- g_free (search_text_copy);
+ while (token_index < token_array->len)
+ {
+ field_name = g_ptr_array_index (token_array, token_index);
+ token_index++;
- return FALSE;
+ if (token_index == token_array->len)
+ {
+ break;
+ }
+
+ field_value = g_ptr_array_index (token_array, token_index);
+ token_index++;
+
+ if (case_sensetive)
+ {
+ matches = (strstr ("_COMM", field_name) &&
+ comm &&
+ strstr (comm, field_value)) ||
+ (strstr ("_MESSAGE", field_name) &&
+ message &&
+ strstr (message, field_value)) ||
+ (strstr ("_KERNEL_DEVICE", field_name) &&
+ kernel_device &&
+ strstr (kernel_device, field_value)) ||
+ (strstr ("_AUDIT_SESSION", field_name) &&
+ audit_session &&
+ strstr (audit_session, field_value));
+ }
+ else
+ {
+ matches = (utf8_strcasestr ("_comm", field_name) &&
+ comm &&
+ strstr (comm, field_value)) ||
+ (utf8_strcasestr ("_message", field_name) &&
+ message &&
+ strstr (message, field_value)) ||
+ (utf8_strcasestr ("_kernel_device", field_name) &&
+ kernel_device &&
+ strstr (kernel_device, field_value)) ||
+ (utf8_strcasestr ("_audit_session", field_name) &&
+ audit_session &&
+ strstr (audit_session, field_value));
+ }
+
+ match_stack[match_count] = matches;
+ match_count++;
+
+ if (token_index == token_array->len)
+ {
+ break;
+ }
+
+ if (g_strcmp0 (g_ptr_array_index (token_array, token_index), " ") == 0)
+ {
+ match_stack[match_count] = LOGICAL_AND;
+ match_count++;
+ token_index++;
+ }
+ else if (g_strcmp0 (g_ptr_array_index (token_array, token_index),
+ "+") == 0)
+ {
+ match_stack[match_count] = LOGICAL_OR;
+ match_count++;
+ token_index++;
+ }
+ }
+
+ if (match_count > 2)
+ {
+ for (i = 0; i < match_count; i++)
+ {
+ if (match_stack[i] == 3)
+ {
+ int j;
+
+ match_stack[i - 1] = match_stack[i - 1] && match_stack[i + 1];
+
+ for (j = i; j < match_count - 2; j++)
+ {
+ if (j == match_count - 3)
+ {
+ match_stack[j] = match_stack[j + 2];
+ /* We use -1 to represent the values that are not useful */
+ match_stack[j + 1] = -1;
+
+ break;
+ }
+
+ match_stack[j] = match_stack[j + 2];
+ match_stack[j + 2] = -1;
+ }
+ }
+ }
+
+ for (i = 0; i < match_count; i++)
+ {
+ if ((match_stack[i] == 2) && (i != token_index - 1) &&
+ (match_stack[i + 1] != -1))
+ {
+ int j;
+
+ match_stack[i - 1] = match_stack[i - 1] || match_stack[i + 1];
+
+ for (j = i; j < match_count - 2; j++)
+ {
+ match_stack[j] = match_stack[j + 2];
+ match_stack[j + 2] = -1;
+ }
+ }
+ }
+ }
+
+ matches = match_stack[0];
+
+ return matches;
}
static gboolean
-utf8_strcasestr (const gchar *potential_hit,
- const gchar *search_term)
+search_in_result (GlJournalEntry *entry,
+ const gchar *search_text)
{
- gchar *folded;
- gboolean matches;
+ gboolean matches;
+ gchar *search_text_copy;
+ GPtrArray *token_array;
- folded = g_utf8_casefold (potential_hit, -1);
- matches = strstr (folded, search_term) != NULL;
+ search_text_copy = g_strdup (search_text);
- g_free (folded);
- return matches;
+ token_array = tokenize_search_string (search_text_copy);
+ matches = calculate_match (entry, token_array, TRUE);
+
+ g_ptr_array_free (token_array, TRUE);
+
+ return matches;
}
static void
@@ -201,50 +408,18 @@ listbox_search_filter_func (GtkListBoxRow *row,
}
else
{
- gchar *field_name;
- gchar *field_value;
- gchar *search_text_copy;
- const gchar *comm;
- const gchar *message;
- const gchar *kernel_device;
- const gchar *audit_session;
gboolean matches;
-
- comm = gl_journal_entry_get_command_line (entry);
- message = gl_journal_entry_get_message (entry);
- kernel_device = gl_journal_entry_get_kernel_device (entry);
- audit_session = gl_journal_entry_get_audit_session (entry);
+ gchar *search_text_copy;
+ GPtrArray *token_array;
search_text_copy = g_strdup (priv->search_text);
- field_name = strtok (search_text_copy, "=");
- field_value = strtok (NULL, " ");
- if (field_value == NULL)
- {
- matches = (comm && utf8_strcasestr (comm, priv->search_text)) ||
- (message && utf8_strcasestr (message, priv->search_text)) ||
- (kernel_device && utf8_strcasestr (kernel_device, priv->search_text)) ||
- (audit_session && utf8_strcasestr (audit_session, priv->search_text));
+ token_array = tokenize_search_string (search_text_copy);
+ matches = calculate_match (entry, token_array, FALSE);
- g_free (search_text_copy);
+ g_ptr_array_free (token_array, TRUE);
- return matches;
- }
- else
- {
- matches = (utf8_strcasestr ("_comm", field_name) &&
- comm && strstr (comm, field_value)) ||
- (utf8_strcasestr ("_message", field_name) &&
- message && strstr (message, field_value)) ||
- (utf8_strcasestr ("_kernel_device", field_name) &&
- kernel_device && strstr (kernel_device, field_value)) ||
- (utf8_strcasestr ("_audit_session", field_name) &&
- audit_session && strstr (audit_session, field_value));
-
- g_free (search_text_copy);
-
- return matches;
- }
+ return matches;
}
}