[ghex/expand-search-options: 5/12] Add new HexDocument API to expand search options
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex/expand-search-options: 5/12] Add new HexDocument API to expand search options
- Date: Mon, 25 Apr 2022 21:46:14 +0000 (UTC)
commit b2ba3a5ef31f9740615a1b5db72db1c34464758d
Author: Logan Rathbone <poprocks gmail com>
Date: Tue Apr 19 19:37:29 2022 -0400
Add new HexDocument API to expand search options
src/hex-document.c | 330 +++++++++++++++++++++++++++++++++++++++--------------
src/hex-document.h | 23 ++++
2 files changed, 269 insertions(+), 84 deletions(-)
---
diff --git a/src/hex-document.c b/src/hex-document.c
index f47ed66..fdd7f97 100644
--- a/src/hex-document.c
+++ b/src/hex-document.c
@@ -52,6 +52,7 @@ static void undo_stack_ascend (HexDocument *doc);
static void undo_stack_free (HexDocument *doc);
#define DEFAULT_UNDO_DEPTH 1024
+#define REGEX_SEARCH_LEN 1024 /* FIXME/TODO: This is kind of lazy. Stopgap? */
enum {
DOCUMENT_CHANGED,
@@ -83,7 +84,6 @@ hex_document_find_data_copy (HexDocumentFindData *data)
G_DEFINE_BOXED_TYPE (HexDocumentFindData, hex_document_find_data,
hex_document_find_data_copy, g_free)
-
/* HexChangeData GType Definitions */
/* FIXME - unused and could be unreliable */
@@ -1095,6 +1095,101 @@ hex_document_export_html (HexDocument *doc,
return TRUE;
}
+int
+hex_document_compare_data_full (HexDocument *doc,
+ HexDocumentFindData *find_data,
+ gint64 pos)
+{
+ char *cp = 0;
+ GError *local_error = NULL;
+ int retval = 1; /* match will make it zero, so set it non-zero now. */
+
+ g_return_val_if_fail (find_data, 0);
+ g_return_val_if_fail (find_data->what, 0);
+
+ if (find_data->flags & HEX_SEARCH_REGEX)
+ {
+ GRegex *regex;
+ GMatchInfo *match_info;
+ char *regex_search_str;
+ GRegexCompileFlags regex_compile_flags;
+
+ /* GRegex doesn't let you specify the length of the search string, so
+ * it needs to be NULL-terminated.
+ */
+ regex_search_str = g_malloc (find_data->len+1);
+ memcpy (regex_search_str, find_data->what, find_data->len);
+ regex_search_str[find_data->len] = 0;
+
+ /* match string doesn't have to be UTF-8 */
+ regex_compile_flags = G_REGEX_RAW;
+
+ if (find_data->flags & HEX_SEARCH_IGNORE_CASE)
+ regex_compile_flags |= G_REGEX_CASELESS;
+
+ regex = g_regex_new (regex_search_str,
+ regex_compile_flags,
+ G_REGEX_MATCH_ANCHORED,
+ &local_error);
+
+ g_free (regex_search_str);
+
+ /* sanity check */
+ if (!regex || local_error)
+ {
+ g_debug ("%s: error: %s", __func__, local_error->message);
+ goto out;
+ }
+
+ cp = hex_buffer_get_data (doc->buffer, pos, REGEX_SEARCH_LEN);
+
+ if (g_regex_match_full (regex, cp,
+ REGEX_SEARCH_LEN, /* length of string being searched */
+ 0, /* start pos */
+ 0, /* addl match_options */
+ &match_info,
+ &local_error))
+ {
+ char *word = g_match_info_fetch (match_info, 0);
+
+ g_debug ("Found: %s", word);
+ find_data->found_len = strlen (word);
+ g_free (word);
+ retval = 0;
+ }
+ else
+ {
+ if (local_error)
+ {
+ g_debug ("%s: error: %s",
+ __func__,
+ local_error ? local_error->message : NULL);
+ }
+ retval = 1;
+ }
+ }
+ else /* non regex */
+ {
+ cp = hex_buffer_get_data (doc->buffer, pos, find_data->len);
+
+ if (find_data->flags & HEX_SEARCH_IGNORE_CASE)
+ {
+ retval = g_ascii_strncasecmp (cp, find_data->what, find_data->len);
+ }
+ else
+ {
+ retval = memcmp (cp, find_data->what, find_data->len);
+ }
+
+ if (retval == 0)
+ find_data->found_len = find_data->len;
+ }
+out:
+ g_clear_error (&local_error);
+ g_free (cp);
+ return retval;
+}
+
/**
* hex_document_compare_data:
* @doc: a [class@Hex.Document] object
@@ -1110,19 +1205,41 @@ int
hex_document_compare_data (HexDocument *doc,
const char *what, gint64 pos, size_t len)
{
- char c;
+ int retval;
+ HexDocumentFindData *find_data = g_new0 (HexDocumentFindData, 1);
- g_return_val_if_fail (what, 0);
+ find_data->what = what;
+ find_data->len = len;
+ find_data->flags = HEX_SEARCH_NONE;
- for (size_t i = 0; i < len; i++, what++)
- {
- c = hex_buffer_get_byte (doc->buffer, pos + i);
+ retval = hex_document_compare_data_full (doc, find_data, pos);
+ g_free (find_data);
+
+ return retval;
+}
+
+gboolean
+hex_document_find_forward_full (HexDocument *doc,
+ HexDocumentFindData *find_data)
+{
+ gint64 pos;
+ gint64 payload = hex_buffer_get_payload_size (
+ hex_document_get_buffer (doc));
- if (c != *what)
- return (c - *what);
+ g_return_val_if_fail (find_data != NULL, FALSE);
+
+ pos = find_data->start;
+ while (pos < payload)
+ {
+ if (hex_document_compare_data_full (doc, find_data, pos) == 0)
+ {
+ find_data->offset = pos;
+ return TRUE;
+ }
+ pos++;
}
-
- return 0;
+
+ return FALSE;
}
/**
@@ -1148,22 +1265,20 @@ gboolean
hex_document_find_forward (HexDocument *doc, gint64 start, const char *what,
size_t len, gint64 *offset)
{
- gint64 pos;
- gint64 payload = hex_buffer_get_payload_size (
- hex_document_get_buffer (doc));
+ gboolean retval;
+ HexDocumentFindData *find_data = g_new0 (HexDocumentFindData, 1);
- pos = start;
- while (pos < payload)
- {
- if (hex_document_compare_data (doc, what, pos, len) == 0)
- {
- *offset = pos;
- return TRUE;
- }
- pos++;
- }
+ find_data->start = start;
+ find_data->what = what;
+ find_data->len = len;
+ find_data->flags = HEX_SEARCH_NONE;
- return FALSE;
+ retval = hex_document_find_forward_full (doc, find_data);
+ *offset = find_data->offset;
+
+ g_free (find_data);
+
+ return retval;
}
/**
@@ -1185,6 +1300,26 @@ hex_document_find_finish (HexDocument *doc,
return g_task_propagate_pointer (G_TASK(result), NULL);
}
+#define FIND_FULL_THREAD_TEMPLATE(FUNC_NAME, FUNC_TO_CALL) \
+static void \
+FUNC_NAME (GTask *task, \
+ gpointer source_object, \
+ gpointer task_data, \
+ GCancellable *cancellable) \
+{ \
+ HexDocument *doc = HEX_DOCUMENT (source_object); \
+ HexDocumentFindData *find_data = task_data; \
+ \
+ g_return_if_fail (find_data); \
+ \
+ find_data->found = FUNC_TO_CALL (doc, find_data); \
+ \
+ g_task_return_pointer (task, find_data, g_free); \
+}
+
+FIND_FULL_THREAD_TEMPLATE(hex_document_find_forward_full_thread,
+ hex_document_find_forward_full)
+
static void
hex_document_find_forward_thread (GTask *task,
gpointer source_object,
@@ -1201,6 +1336,25 @@ hex_document_find_forward_thread (GTask *task,
g_task_return_pointer (task, find_data, g_free);
}
+#define FIND_FULL_ASYNC_TEMPLATE(FUNC_NAME, FUNC_TO_CALL) \
+void \
+FUNC_NAME (HexDocument *doc, \
+ HexDocumentFindData *find_data, \
+ GCancellable *cancellable, \
+ GAsyncReadyCallback callback, \
+ gpointer user_data) \
+{ \
+ GTask *task; \
+ \
+ task = g_task_new (doc, cancellable, callback, user_data); \
+ g_task_set_return_on_cancel (task, TRUE); \
+ g_task_set_task_data (task, find_data, g_free); \
+ g_task_run_in_thread (task, FUNC_TO_CALL); \
+}
+
+FIND_FULL_ASYNC_TEMPLATE(hex_document_find_forward_full_async,
+ hex_document_find_forward_full_thread)
+
/* CROSSREF: hex-document.h - HexDocumentFindData */
/**
* hex_document_find_forward_async:
@@ -1221,31 +1375,57 @@ hex_document_find_forward_thread (GTask *task,
* function that should generally be used by a GUI client to find a string
* forwards in a #HexDocument.
*/
-void
-hex_document_find_forward_async (HexDocument *doc,
- gint64 start,
- const char *what,
- size_t len,
- gint64 *offset,
- const char *found_msg,
- const char *not_found_msg,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+
+#define FIND_ASYNC_TEMPLATE(FUNC_NAME, FUNC_TO_CALL) \
+void \
+FUNC_NAME (HexDocument *doc, \
+ gint64 start, \
+ const char *what, \
+ size_t len, \
+ gint64 *offset, \
+ const char *found_msg, \
+ const char *not_found_msg, \
+ GCancellable *cancellable, \
+ GAsyncReadyCallback callback, \
+ gpointer user_data) \
+{ \
+ GTask *task; \
+ HexDocumentFindData *find_data = g_new0 (HexDocumentFindData, 1); \
+ \
+ find_data->start = start; \
+ find_data->what = what; \
+ find_data->len = len; \
+ find_data->found_msg = found_msg; \
+ find_data->not_found_msg = not_found_msg; \
+ \
+ task = g_task_new (doc, cancellable, callback, user_data); \
+ g_task_set_return_on_cancel (task, TRUE); \
+ g_task_set_task_data (task, find_data, g_free); \
+ g_task_run_in_thread (task, FUNC_TO_CALL); \
+ g_object_unref (task); /* _run_in_thread takes a ref */ \
+}
+
+FIND_ASYNC_TEMPLATE(hex_document_find_forward_async,
+ hex_document_find_forward_thread)
+
+gboolean
+hex_document_find_backward_full (HexDocument *doc,
+ HexDocumentFindData *find_data)
{
- GTask *task;
- HexDocumentFindData *find_data = g_new0 (HexDocumentFindData, 1);
+ gint64 pos = find_data->start;
+
+ if (pos == 0)
+ return FALSE;
- find_data->start = start;
- find_data->what = what;
- find_data->len = len;
- find_data->found_msg = found_msg;
- find_data->not_found_msg = not_found_msg;
+ do {
+ pos--;
+ if (hex_document_compare_data_full (doc, find_data, pos) == 0) {
+ find_data->offset = pos;
+ return TRUE;
+ }
+ } while (pos > 0);
- task = g_task_new (doc, cancellable, callback, user_data);
- g_task_set_return_on_cancel (task, TRUE);
- g_task_set_task_data (task, find_data, g_free);
- g_task_run_in_thread (task, hex_document_find_forward_thread);
+ return FALSE;
}
/**
@@ -1271,22 +1451,25 @@ gboolean
hex_document_find_backward (HexDocument *doc, gint64 start, const char *what,
size_t len, gint64 *offset)
{
- gint64 pos = start;
-
- if (pos == 0)
- return FALSE;
+ gboolean retval;
+ HexDocumentFindData *find_data = g_new0 (HexDocumentFindData, 1);
- do {
- pos--;
- if (hex_document_compare_data (doc, what, pos, len) == 0) {
- *offset = pos;
- return TRUE;
- }
- } while (pos > 0);
+ find_data->start = start;
+ find_data->what = what;
+ find_data->len = len;
+ find_data->flags = HEX_SEARCH_NONE;
- return FALSE;
+ retval = hex_document_find_backward_full (doc, find_data);
+ *offset = find_data->offset;
+
+ g_free (find_data);
+
+ return retval;
}
+FIND_FULL_THREAD_TEMPLATE(hex_document_find_backward_full_thread,
+ hex_document_find_backward_full)
+
static void
hex_document_find_backward_thread (GTask *task,
gpointer source_object,
@@ -1303,6 +1486,9 @@ hex_document_find_backward_thread (GTask *task,
g_task_return_pointer (task, find_data, g_free);
}
+FIND_FULL_ASYNC_TEMPLATE(hex_document_find_backward_full_async,
+ hex_document_find_backward_full_thread)
+
/**
* hex_document_find_backward_async:
* @doc: a [class@Hex.Document] object
@@ -1322,32 +1508,8 @@ hex_document_find_backward_thread (GTask *task,
* function that should generally be used by a GUI client to find a string
* backwards in a #HexDocument.
*/
-void
-hex_document_find_backward_async (HexDocument *doc,
- gint64 start,
- const char *what,
- size_t len,
- gint64 *offset,
- const char *found_msg,
- const char *not_found_msg,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GTask *task;
- HexDocumentFindData *find_data = g_new0 (HexDocumentFindData, 1);
-
- find_data->start = start;
- find_data->what = what;
- find_data->len = len;
- find_data->found_msg = found_msg;
- find_data->not_found_msg = not_found_msg;
-
- task = g_task_new (doc, cancellable, callback, user_data);
- g_task_set_return_on_cancel (task, TRUE);
- g_task_set_task_data (task, find_data, g_free);
- g_task_run_in_thread (task, hex_document_find_backward_thread);
-}
+FIND_ASYNC_TEMPLATE(hex_document_find_backward_async,
+ hex_document_find_backward_thread)
/**
* hex_document_undo:
diff --git a/src/hex-document.h b/src/hex-document.h
index 41f09f4..1dc238c 100644
--- a/src/hex-document.h
+++ b/src/hex-document.h
@@ -55,6 +55,13 @@ typedef enum
HEX_CHANGE_BYTE
} HexChangeType;
+typedef enum
+{
+ HEX_SEARCH_NONE = 0,
+ HEX_SEARCH_REGEX = 1 << 0,
+ HEX_SEARCH_IGNORE_CASE = 1 << 1,
+} HexSearchFlags;
+
/**
* HexDocumentFindData:
* @found: whether the string was found
@@ -80,7 +87,9 @@ typedef struct
gint64 start;
const char *what;
size_t len;
+ HexSearchFlags flags; /* TODO: Since: 4.1 */
gint64 offset;
+ size_t found_len; /* TODO: Since: 4.1 */
const char *found_msg;
const char *not_found_msg;
} HexDocumentFindData;
@@ -159,20 +168,34 @@ gboolean hex_document_undo (HexDocument *doc);
gboolean hex_document_redo (HexDocument *doc);
int hex_document_compare_data (HexDocument *doc, const char *what,
gint64 pos, size_t len);
+int hex_document_compare_data_full (HexDocument *doc,
+ HexDocumentFindData *find_data, gint64 pos);
gboolean hex_document_find_forward (HexDocument *doc, gint64 start,
const char *what, size_t len, gint64 *offset);
+gboolean hex_document_find_forward_full (HexDocument *doc,
+ HexDocumentFindData *find_data);
void hex_document_find_forward_async (HexDocument *doc, gint64 start,
const char *what, size_t len, gint64 *offset, const char *found_msg,
const char *not_found_msg, GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer user_data);
+void hex_document_find_forward_full_async (HexDocument *doc,
+ HexDocumentFindData *find_data, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data);
+
gboolean hex_document_find_backward (HexDocument *doc, gint64 start,
const char *what, size_t len, gint64 *offset);
+
+gboolean hex_document_find_backward_full (HexDocument *doc,
+ HexDocumentFindData *find_data);
void hex_document_find_backward_async (HexDocument *doc, gint64 start,
const char *what, size_t len, gint64 *offset, const char *found_msg,
const char *not_found_msg, GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer user_data);
+void hex_document_find_backward_full_async (HexDocument *doc,
+ HexDocumentFindData *find_data, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data);
HexDocumentFindData *
hex_document_find_finish (HexDocument *doc, GAsyncResult *result);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]