[ghex] lib: async write API for HexDocument and HexBuffer



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]