Commit 5e871532 authored by Christian Hergert's avatar Christian Hergert
Browse files

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.
parent d6cdec81
......@@ -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;
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment