[gnome-builder] subprocess: add async utf8 communicate API



commit 5e8715328cb39ec8692ec60ce802346e233511eb
Author: Christian Hergert <chergert redhat com>
Date:   Tue Mar 14 19:13:01 2017 -0700

    subprocess: add async utf8 communicate API
    
    This was missing from subprocess, and it can be very helpful when working
    with subprocesses in Python to avoid converting things to GBytes.

 libide/subprocess/ide-breakout-subprocess.c |   20 +++---
 libide/subprocess/ide-subprocess.c          |  111 +++++++++++++++++++++++++++
 libide/subprocess/ide-subprocess.h          |   10 +++
 3 files changed, 131 insertions(+), 10 deletions(-)
---
diff --git a/libide/subprocess/ide-breakout-subprocess.c b/libide/subprocess/ide-breakout-subprocess.c
index 0426f51..8fdc1d5 100644
--- a/libide/subprocess/ide-breakout-subprocess.c
+++ b/libide/subprocess/ide-breakout-subprocess.c
@@ -332,11 +332,11 @@ ide_breakout_subprocess_wait_finish (IdeSubprocess  *subprocess,
 }
 
 void
-ide_subprocess_communicate_utf8_async (IdeSubprocess       *subprocess,
-                                       const char          *stdin_buf,
-                                       GCancellable        *cancellable,
-                                       GAsyncReadyCallback  callback,
-                                       gpointer             user_data)
+ide_breakout_subprocess_communicate_utf8_async (IdeSubprocess       *subprocess,
+                                                const char          *stdin_buf,
+                                                GCancellable        *cancellable,
+                                                GAsyncReadyCallback  callback,
+                                                gpointer             user_data)
 {
   IdeBreakoutSubprocess *self = (IdeBreakoutSubprocess *)subprocess;
   g_autoptr(GBytes) stdin_bytes = NULL;
@@ -396,11 +396,11 @@ communicate_result_validate_utf8 (const char            *stream_name,
 }
 
 gboolean
-ide_subprocess_communicate_utf8_finish (IdeSubprocess  *subprocess,
-                                        GAsyncResult   *result,
-                                        char          **stdout_buf,
-                                        char          **stderr_buf,
-                                        GError        **error)
+ide_breakout_subprocess_communicate_utf8_finish (IdeSubprocess  *subprocess,
+                                                 GAsyncResult   *result,
+                                                 char          **stdout_buf,
+                                                 char          **stderr_buf,
+                                                 GError        **error)
 {
   gboolean ret = FALSE;
   CommunicateState *state;
diff --git a/libide/subprocess/ide-subprocess.c b/libide/subprocess/ide-subprocess.c
index 5a90dc4..c097647 100644
--- a/libide/subprocess/ide-subprocess.c
+++ b/libide/subprocess/ide-subprocess.c
@@ -18,6 +18,8 @@
 
 #define G_LOG_DOMAIN "ide-subprocess"
 
+#include <string.h>
+
 #include "ide-debug.h"
 
 #include "subprocess/ide-subprocess.h"
@@ -310,6 +312,23 @@ ide_subprocess_communicate_utf8 (IdeSubprocess  *self,
   return WRAP_INTERFACE_METHOD (self, communicate_utf8, FALSE, stdin_buf, cancellable, stdout_buf, 
stderr_buf, error);
 }
 
+/**
+ * ide_subprocess_communicate_async:
+ * @self: An #IdeSubprocess
+ * @stdin_buf: (nullable): A #GBytes to send to stdin or %NULL
+ * @cancellable: (nullable): A #GCancellable or %NULL
+ * @callback: A callback to complete the request
+ * @user_data: user data for @callback
+ *
+ * Asynchronously communicates with the the child process.
+ *
+ * There is no need to call ide_subprocess_wait() on the process if using
+ * this asynchronous operation as it will internally wait for the child
+ * to exit or be signaled.
+ *
+ * Ensure you've set the proper flags to ensure that you can write to stdin
+ * or read from stderr/stdout as necessary.
+ */
 void
 ide_subprocess_communicate_async (IdeSubprocess       *self,
                                   GBytes              *stdin_buf,
@@ -323,6 +342,18 @@ ide_subprocess_communicate_async (IdeSubprocess       *self,
   WRAP_INTERFACE_METHOD (self, communicate_async, NULL, stdin_buf, cancellable, callback, user_data);
 }
 
+/**
+ * ide_subprocess_communicate_finish:
+ * @self: An #IdeSubprocess
+ * @result: A #GAsyncResult
+ * @stdout_buf: (out) (optional): A location for a #Bytes.
+ * @stderr_buf: (out) (optional): A location for a #Bytes.
+ * @error: a location for a #GError
+ *
+ * Finishes a request to ide_subprocess_communicate_async().
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ */
 gboolean
 ide_subprocess_communicate_finish (IdeSubprocess  *self,
                                    GAsyncResult   *result,
@@ -336,6 +367,86 @@ ide_subprocess_communicate_finish (IdeSubprocess  *self,
   return WRAP_INTERFACE_METHOD (self, communicate_finish, FALSE, result, stdout_buf, stderr_buf, error);
 }
 
+/**
+ * ide_subprocess_communicate_utf8_async:
+ * @stdin_buf: (nullable): The data to send to stdin or %NULL
+ *
+ */
+void
+ide_subprocess_communicate_utf8_async (IdeSubprocess       *self,
+                                       const gchar         *stdin_buf,
+                                       GCancellable        *cancellable,
+                                       GAsyncReadyCallback  callback,
+                                       gpointer             user_data)
+{
+  g_autoptr(GBytes) stdin_bytes = NULL;
+
+  g_return_if_fail (IDE_IS_SUBPROCESS (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  if (stdin_buf)
+    stdin_bytes = g_bytes_new (stdin_buf, strlen (stdin_buf));
+
+  ide_subprocess_communicate_async (self, stdin_bytes, cancellable, callback, user_data);
+}
+
+static gchar *
+get_utf8_bytes (GBytes *bytes)
+{
+  const gchar *data;
+  gsize size;
+
+  data = g_bytes_get_data (bytes, &size);
+
+  if (size < G_MAXSIZE && g_utf8_validate (data, size, NULL))
+    return g_strndup (data, size);
+
+  return NULL;
+}
+
+/**
+ * ide_subprocess_communicate_utf8_finish:
+ * @self: An #IdeSubprocess
+ * @result: A #GAsyncResult
+ * @stdout_buf: (out) (optional): A location for the UTF-8 formatted output string or %NULL
+ * @stderr_buf: (out) (optional): A location for the UTF-8 formatted output string or %NULL
+ * @error: A location for a #GError, or %NULL
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ */
+gboolean
+ide_subprocess_communicate_utf8_finish (IdeSubprocess  *self,
+                                        GAsyncResult   *result,
+                                        gchar         **stdout_buf,
+                                        gchar         **stderr_buf,
+                                        GError        **error)
+{
+  g_autoptr(GBytes) stdout_bytes = NULL;
+  g_autoptr(GBytes) stderr_bytes = NULL;
+
+  g_return_val_if_fail (IDE_IS_SUBPROCESS (self), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  if (ide_subprocess_communicate_finish (self, result, &stdout_bytes, &stderr_bytes, error))
+    {
+      if (stdout_bytes && stdout_buf)
+        *stdout_buf = get_utf8_bytes (stdout_bytes);
+
+      if (stderr_bytes && stderr_buf)
+        *stderr_buf = get_utf8_bytes (stderr_bytes);
+
+      return TRUE;
+    }
+
+  if (stdout_buf)
+    *stdout_buf = NULL;
+
+  if (stderr_buf)
+    *stderr_buf = NULL;
+
+  return FALSE;
+}
+
 gboolean
 ide_subprocess_check_exit_status (IdeSubprocess  *self,
                                   GError        **error)
diff --git a/libide/subprocess/ide-subprocess.h b/libide/subprocess/ide-subprocess.h
index 557bc98..a1a138e 100644
--- a/libide/subprocess/ide-subprocess.h
+++ b/libide/subprocess/ide-subprocess.h
@@ -135,6 +135,16 @@ gboolean       ide_subprocess_communicate_finish (IdeSubprocess        *self,
                                                   GBytes              **stdout_buf,
                                                   GBytes              **stderr_buf,
                                                   GError              **error);
+void           ide_subprocess_communicate_utf8_async  (IdeSubprocess        *self,
+                                                       const gchar          *stdin_buf,
+                                                       GCancellable         *cancellable,
+                                                       GAsyncReadyCallback   callback,
+                                                       gpointer              user_data);
+gboolean       ide_subprocess_communicate_utf8_finish (IdeSubprocess        *self,
+                                                       GAsyncResult         *result,
+                                                       gchar               **stdout_buf,
+                                                       gchar               **stderr_buf,
+                                                       GError              **error);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]