[ghex] lib: async write API for HexDocument and HexBuffer
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex] lib: async write API for HexDocument and HexBuffer
- Date: Wed, 29 Dec 2021 22:44:34 +0000 (UTC)
commit b7519f2202c8c4517c4270200263a3d5b71b0f28
Author: Logan Rathbone <poprocks gmail com>
Date: Wed Dec 29 17:39:55 2021 -0500
lib: async write API for HexDocument and HexBuffer
nb: Not currently used by the GHex app.
src/hex-buffer-iface.c | 54 +++++++++++++++++++
src/hex-buffer-iface.h | 20 +++++++
src/hex-buffer-malloc.c | 45 ++++++++++++++++
src/hex-buffer-mmap.c | 54 +++++++++++++++++--
src/hex-document.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++-
src/hex-document.h | 9 ++++
6 files changed, 317 insertions(+), 4 deletions(-)
---
diff --git a/src/hex-buffer-iface.c b/src/hex-buffer-iface.c
index 23245fa..b820b15 100644
--- a/src/hex-buffer-iface.c
+++ b/src/hex-buffer-iface.c
@@ -251,6 +251,60 @@ hex_buffer_write_to_file (HexBuffer *self, GFile *file)
return iface->write_to_file (self, file);
}
+/**
+ * hex_buffer_write_to_file_async:
+ * @file: #GFile to write to
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): function to be called when the operation is
+ * complete
+ *
+ * Write the buffer to the #GFile specified. This is the non-blocking
+ * version of [method@Hex.Buffer.write_to_file].
+ */
+void
+hex_buffer_write_to_file_async (HexBuffer *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ HexBufferInterface *iface;
+
+ g_return_if_fail (HEX_IS_BUFFER (self));
+ iface = HEX_BUFFER_GET_IFACE (self);
+ g_return_if_fail (iface->write_to_file_async != NULL);
+
+ iface->write_to_file_async (self, file, cancellable, callback, user_data);
+}
+
+/**
+ * hex_buffer_write_to_file_finish:
+ * @result: result of the task
+ * @error: (nullable): optional pointer to a #GError object to populate with
+ * any error returned by the task
+ *
+ * Obtain the result of a completed write-to-file operation.
+ *
+ * This method is typically called from the #GAsyncReadyCallback function
+ * passed to [method@Hex.Buffer.write_to_file_async] to obtain the result of
+ * the operation.
+ *
+ * Returns: %TRUE if the operation was successful; %FALSE otherwise.
+ */
+gboolean
+hex_buffer_write_to_file_finish (HexBuffer *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ HexBufferInterface *iface;
+
+ g_return_val_if_fail (HEX_IS_BUFFER (self), FALSE);
+ iface = HEX_BUFFER_GET_IFACE (self);
+ g_return_val_if_fail (iface->write_to_file_finish != NULL, FALSE);
+
+ return iface->write_to_file_finish (self, result, error);
+}
+
/**
* hex_buffer_get_payload_size:
*
diff --git a/src/hex-buffer-iface.h b/src/hex-buffer-iface.h
index b55aa83..47c9506 100644
--- a/src/hex-buffer-iface.h
+++ b/src/hex-buffer-iface.h
@@ -72,6 +72,16 @@ struct _HexBufferInterface
gboolean (*write_to_file) (HexBuffer *self,
GFile *file);
+ void (*write_to_file_async) (HexBuffer *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ gboolean (*write_to_file_finish) (HexBuffer *self,
+ GAsyncResult *result,
+ GError **error);
+
gint64 (*get_payload_size) (HexBuffer *self);
/* --- padding starts here -- started w/ 12 extra vfuncs --- */
@@ -108,6 +118,16 @@ gboolean hex_buffer_read_finish (HexBuffer *buf, GAsyncResult *result,
gboolean hex_buffer_write_to_file (HexBuffer *self,
GFile *file);
+void hex_buffer_write_to_file_async (HexBuffer *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean hex_buffer_write_to_file_finish (HexBuffer *self,
+ GAsyncResult *result,
+ GError **error);
+
gint64 hex_buffer_get_payload_size (HexBuffer *self);
/* Common utility functions */
diff --git a/src/hex-buffer-malloc.c b/src/hex-buffer-malloc.c
index b9fd7a8..d1599cf 100644
--- a/src/hex-buffer-malloc.c
+++ b/src/hex-buffer-malloc.c
@@ -425,6 +425,49 @@ out:
return ret;
}
+static gboolean
+hex_buffer_malloc_write_to_file_finish (HexBuffer *buf,
+ GAsyncResult *result,
+ GError **error)
+{
+ HexBufferMalloc *self = HEX_BUFFER_MALLOC (buf);
+
+ g_return_val_if_fail (g_task_is_valid (result, G_OBJECT(self)), FALSE);
+
+ return g_task_propagate_boolean (G_TASK(result), error);
+}
+
+static void
+hex_buffer_malloc_write_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ HexBufferMalloc *self = HEX_BUFFER_MALLOC (source_object);
+ GFile *file = G_FILE (task_data);
+ gboolean success;
+
+ success = hex_buffer_malloc_write_to_file (HEX_BUFFER(self), file);
+
+ g_task_return_boolean (task, success);
+}
+
+static void
+hex_buffer_malloc_write_to_file_async (HexBuffer *buf,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ HexBufferMalloc *self = HEX_BUFFER_MALLOC (buf);
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, file, NULL);
+ g_task_run_in_thread (task, hex_buffer_malloc_write_thread);
+ g_object_unref (task); /* _run_in_thread takes a ref */
+}
+
static gint64
hex_buffer_malloc_get_payload_size (HexBuffer *buf)
{
@@ -519,5 +562,7 @@ hex_buffer_malloc_iface_init (HexBufferInterface *iface)
iface->read_async = hex_buffer_malloc_read_async;
iface->read_finish = hex_buffer_malloc_read_finish;
iface->write_to_file = hex_buffer_malloc_write_to_file;
+ iface->write_to_file_async = hex_buffer_malloc_write_to_file_async;
+ iface->write_to_file_finish = hex_buffer_malloc_write_to_file_finish;
iface->get_payload_size = hex_buffer_malloc_get_payload_size;
}
diff --git a/src/hex-buffer-mmap.c b/src/hex-buffer-mmap.c
index ab16dd5..bb49d5d 100644
--- a/src/hex-buffer-mmap.c
+++ b/src/hex-buffer-mmap.c
@@ -722,7 +722,7 @@ hex_buffer_mmap_read_finish (HexBuffer *buf,
}
static void
-hex_buffer_mmap_thread (GTask *task,
+hex_buffer_mmap_read_thread (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
@@ -747,7 +747,7 @@ hex_buffer_mmap_read_async (HexBuffer *buf,
GTask *task;
task = g_task_new (self, cancellable, callback, user_data);
- g_task_run_in_thread (task, hex_buffer_mmap_thread);
+ g_task_run_in_thread (task, hex_buffer_mmap_read_thread);
g_object_unref (task); /* _run_in_thread takes a ref */
}
@@ -771,7 +771,8 @@ static gboolean hex_buffer_mmap_set_data (HexBuffer *buf,
return TRUE;
}
-static gboolean hex_buffer_mmap_write_to_file (HexBuffer *buf,
+static gboolean
+hex_buffer_mmap_write_to_file (HexBuffer *buf,
GFile *file)
{
HexBufferMmap *self = HEX_BUFFER_MMAP (buf);
@@ -795,6 +796,51 @@ static gboolean hex_buffer_mmap_write_to_file (HexBuffer *buf,
return retval;
}
+static gboolean
+hex_buffer_mmap_write_to_file_finish (HexBuffer *buf,
+ GAsyncResult *result,
+ GError **error)
+{
+ HexBufferMmap *self = HEX_BUFFER_MMAP (buf);
+
+ g_return_val_if_fail (g_task_is_valid (result, G_OBJECT(self)), FALSE);
+
+ return g_task_propagate_boolean (G_TASK(result), error);
+}
+
+static void
+hex_buffer_mmap_write_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ HexBufferMmap *self = HEX_BUFFER_MMAP (source_object);
+ GFile *file = G_FILE (task_data);
+ gboolean success;
+
+ success = hex_buffer_mmap_write_to_file (HEX_BUFFER(self), file);
+ if (success)
+ g_task_return_boolean (task, TRUE);
+ else
+ g_task_return_error (task, self->error);
+}
+
+static void
+hex_buffer_mmap_write_to_file_async (HexBuffer *buf,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ HexBufferMmap *self = HEX_BUFFER_MMAP (buf);
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, file, NULL);
+ g_task_run_in_thread (task, hex_buffer_mmap_write_thread);
+ g_object_unref (task); /* _run_in_thread takes a ref */
+}
+
/* PUBLIC FUNCTIONS */
/**
@@ -834,5 +880,7 @@ hex_buffer_mmap_iface_init (HexBufferInterface *iface)
iface->read_async = hex_buffer_mmap_read_async;
iface->read_finish = hex_buffer_mmap_read_finish;
iface->write_to_file = hex_buffer_mmap_write_to_file;
+ iface->write_to_file_async = hex_buffer_mmap_write_to_file_async;
+ iface->write_to_file_finish = hex_buffer_mmap_write_to_file_finish;
iface->get_payload_size = hex_buffer_mmap_get_payload_size;
}
diff --git a/src/hex-document.c b/src/hex-document.c
index 1621e0b..2247f9c 100644
--- a/src/hex-document.c
+++ b/src/hex-document.c
@@ -588,7 +588,7 @@ hex_document_delete_data (HexDocument *doc,
* applicable to the document object above and beyond the buffer.
*
* This method is typically called from the #GAsyncReadyCallback function
- * passed to [method@Hex.Buffer.read_async] to obtain the result of the
+ * passed to [method@Hex.Document.read_async] to obtain the result of the
* operation.
*
* Returns: %TRUE if the operation was successful; %FALSE otherwise.
@@ -734,6 +734,143 @@ out:
return ret;
}
+/**
+ * hex_document_write_finish:
+ * @doc: a [class@Hex.Document] object
+ * @result: result of the task
+ * @error: (nullable): optional pointer to a #GError object to populate with
+ * any error returned by the task
+ *
+ * Obtain the result of a completed write-to-file operation.
+ *
+ * Currently, this method is mostly a wrapper around
+ * [method@Hex.Buffer.write_to_file_finish].
+ *
+ * This method is typically called from the #GAsyncReadyCallback function
+ * passed to [method@Hex.Document.write_async] or
+ * [method@Hex.Document.write_to_file_async] to obtain the result of the
+ * operation.
+ *
+ * Returns: %TRUE if the operation was successful; %FALSE otherwise.
+ */
+gboolean
+hex_document_write_finish (HexDocument *doc,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (HEX_IS_DOCUMENT (doc), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK(result), error);
+}
+
+static void
+write_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ HexBuffer *buf = HEX_BUFFER(source_object);
+ GTask *doc_task = G_TASK(user_data);
+ gboolean success;
+ GError *local_error = NULL;
+
+ success = hex_buffer_write_to_file_finish (buf, res, &local_error);
+ g_debug ("%s: DONE -- result: %d", __func__, success);
+
+ if (success)
+ {
+ g_task_return_boolean (doc_task, TRUE);
+ }
+ else
+ {
+ if (local_error)
+ g_task_return_error (doc_task, local_error);
+ else
+ g_task_return_boolean (doc_task, FALSE);
+ }
+
+ g_object_unref (doc_task); /* g_task_return_* takes a ref. */
+}
+
+/**
+ * hex_document_write_async:
+ * @doc: a [class@Hex.Document] object
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): function to be called when the operation is
+ * complete
+ *
+ * Write the buffer to the pre-existing #GFile connected to the #HexDocument
+ * object. This can be used for a 'Save (in place)' operation. This is the
+ * non-blocking version of [method@Hex.Document.write].
+ *
+ * Note that for both this method and
+ * [method@Hex.Document.write_to_file_async],
+ * [method@Hex.Document.write_finish] is the method to retrieve the return
+ * value in your #GAsyncReadyCallback function.
+ */
+void
+hex_document_write_async (HexDocument *doc,
+ GCancellable *cancellable, /* FIXME: presently ignored */
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *doc_task;
+ char *path = NULL;
+
+ g_return_if_fail (G_IS_FILE (doc->file));
+
+ path = g_file_get_path (doc->file);
+ if (! path)
+ goto out;
+
+ doc_task = g_task_new (doc, cancellable, callback, user_data);
+
+ hex_buffer_write_to_file_async (doc->buffer,
+ doc->file,
+ NULL, /* cancellable */
+ write_ready_cb,
+ doc_task);
+
+out:
+ g_free (path);
+}
+
+/**
+ * hex_document_write_to_file_async:
+ * @doc: a [class@Hex.Document] object
+ * @file: #GFile to be written to
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): function to be called when the operation is
+ * complete
+ *
+ * Write the buffer to `file` asynchronously. This can be used for a 'Save As'
+ * operation. This is the non-blocking version of
+ * [method@Hex.Document.write_to_file].
+ *
+ * Note that for both this method and [method@Hex.Document.write_async],
+ * [method@Hex.Document.write_finish] is the method to retrieve the return
+ * value in your #GAsyncReadyCallback function.
+ */
+void
+hex_document_write_to_file_async (HexDocument *doc,
+ GFile *file,
+ GCancellable *cancellable, /* FIXME: presently ignored */
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *doc_task;
+
+ g_return_if_fail (G_IS_FILE (doc->file));
+
+ doc_task = g_task_new (doc, cancellable, callback, user_data);
+
+ hex_buffer_write_to_file_async (doc->buffer,
+ file,
+ NULL, /* cancellable */
+ write_ready_cb,
+ doc_task);
+}
+
/**
* hex_document_changed:
* @doc: a [class@Hex.Document] object
diff --git a/src/hex-document.h b/src/hex-document.h
index 664c34a..41f09f4 100644
--- a/src/hex-document.h
+++ b/src/hex-document.h
@@ -139,6 +139,15 @@ gboolean hex_document_read_finish (HexDocument *doc, GAsyncResult *result,
gboolean hex_document_write (HexDocument *doc);
gboolean hex_document_write_to_file (HexDocument *doc, GFile *file);
+void hex_document_write_to_file_async (HexDocument *doc, GFile *file,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data);
+void hex_document_write_async (HexDocument *doc,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean hex_document_write_finish (HexDocument *doc, GAsyncResult *result,
+ GError **error);
+
gboolean hex_document_export_html (HexDocument *doc, const char *html_path,
const char *base_name, gint64 start, gint64 end, guint cpl, guint lpp,
guint cpw);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]