Tue, 23 Jan 2024 01:34:53 -0600
Remove PurpleQueuedOutputStream
Everything that was using it is now using it from Birb so we can safely delete
it.
Testing Done:
Consulted with the Turtles.
Reviewed at https://reviews.imfreedom.org/r/2933/
| libpurple/meson.build | file | annotate | diff | comparison | revisions | |
| libpurple/queuedoutputstream.c | file | annotate | diff | comparison | revisions | |
| libpurple/queuedoutputstream.h | file | annotate | diff | comparison | revisions | |
| libpurple/tests/meson.build | file | annotate | diff | comparison | revisions | |
| libpurple/tests/test_queued_output_stream.c | file | annotate | diff | comparison | revisions | |
| po/POTFILES.in | file | annotate | diff | comparison | revisions |
--- a/libpurple/meson.build Tue Jan 23 01:24:59 2024 -0600 +++ b/libpurple/meson.build Tue Jan 23 01:34:53 2024 -0600 @@ -102,7 +102,6 @@ 'purplewhiteboard.c', 'purplewhiteboardmanager.c', 'purplewhiteboarduiops.c', - 'queuedoutputstream.c', 'request.c', 'request/purplerequestfield.c', 'request/purplerequestfieldaccount.c', @@ -230,7 +229,6 @@ 'purplewhiteboardmanager.h', 'purplewhiteboardops.h', 'purplewhiteboarduiops.h', - 'queuedoutputstream.h', 'request.h', 'request-datasheet.h', 'roomlist.h',
--- a/libpurple/queuedoutputstream.c Tue Jan 23 01:24:59 2024 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -/* - * Purple - Internet Messaging Library - * Copyright (C) Pidgin Developers <devel@pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <https://www.gnu.org/licenses/>. - */ - -#include "queuedoutputstream.h" - -struct _PurpleQueuedOutputStream -{ - GFilterOutputStream parent; - - GAsyncQueue *queue; - gboolean pending_queued; -} PurpleQueuedOutputStreamPrivate; - -G_DEFINE_TYPE(PurpleQueuedOutputStream, purple_queued_output_stream, - G_TYPE_FILTER_OUTPUT_STREAM) - -/****************************************************************************** - * Helpers - *****************************************************************************/ - -static void purple_queued_output_stream_start_push_bytes_async(GTask *task); - -static void -purple_queued_output_stream_push_bytes_async_cb(GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - GTask *task = G_TASK(user_data); - PurpleQueuedOutputStream *stream = g_task_get_source_object(task); - gssize written; - GBytes *bytes; - gsize size; - GError *error = NULL; - - written = g_output_stream_write_bytes_finish(G_OUTPUT_STREAM(source), - res, &error); - - bytes = g_task_get_task_data(task); - size = g_bytes_get_size(bytes); - - if (written < 0) { - /* Error occurred, return error */ - g_task_return_error(task, error); - g_clear_object(&task); - } else if (size > (gsize)written) { - /* Partial write, prepare to send remaining data */ - bytes = g_bytes_new_from_bytes(bytes, written, size - written); - g_task_set_task_data(task, bytes, (GDestroyNotify)g_bytes_unref); - } else { - /* Full write, this task is finished */ - g_task_return_boolean(task, TRUE); - g_clear_object(&task); - } - - /* If g_task_return_* was called in this function, the callback - * may have cleared the stream. If so, there will be no remaining - * tasks to process here. - */ - - if (task == NULL) { - /* Any queued data left? */ - task = g_async_queue_try_pop(stream->queue); - } - - if (task != NULL) { - /* More to process */ - purple_queued_output_stream_start_push_bytes_async(task); - } else { - /* All done */ - stream->pending_queued = FALSE; - g_output_stream_clear_pending(G_OUTPUT_STREAM(stream)); - } -} - -static void -purple_queued_output_stream_start_push_bytes_async(GTask *task) { - PurpleQueuedOutputStream *stream = g_task_get_source_object(task); - GOutputStream *base_stream = NULL; - GFilterOutputStream *filtered = NULL; - - filtered = G_FILTER_OUTPUT_STREAM(stream); - base_stream = g_filter_output_stream_get_base_stream(filtered); - - g_output_stream_write_bytes_async(base_stream, g_task_get_task_data(task), - g_task_get_priority(task), - g_task_get_cancellable(task), - purple_queued_output_stream_push_bytes_async_cb, - task); -} - -/****************************************************************************** - * GObject Implementation - *****************************************************************************/ -static void -purple_queued_output_stream_dispose(GObject *object) { - PurpleQueuedOutputStream *stream = PURPLE_QUEUED_OUTPUT_STREAM(object); - - g_clear_pointer(&stream->queue, g_async_queue_unref); - - G_OBJECT_CLASS(purple_queued_output_stream_parent_class)->dispose(object); -} - -static void -purple_queued_output_stream_class_init(PurpleQueuedOutputStreamClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - - obj_class->dispose = purple_queued_output_stream_dispose; -} - -static void -purple_queued_output_stream_init(PurpleQueuedOutputStream *stream) { - stream->queue = g_async_queue_new_full((GDestroyNotify)g_bytes_unref); - stream->pending_queued = FALSE; -} - -/****************************************************************************** - * Public API - *****************************************************************************/ -PurpleQueuedOutputStream * -purple_queued_output_stream_new(GOutputStream *base_stream) { - g_return_val_if_fail(G_IS_OUTPUT_STREAM(base_stream), NULL); - - return g_object_new( - PURPLE_TYPE_QUEUED_OUTPUT_STREAM, - "base-stream", base_stream, - NULL); -} - -void -purple_queued_output_stream_push_bytes_async(PurpleQueuedOutputStream *stream, - GBytes *bytes, int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gboolean set_pending; - GError *error = NULL; - - g_return_if_fail(PURPLE_IS_QUEUED_OUTPUT_STREAM(stream)); - g_return_if_fail(bytes != NULL); - - task = g_task_new(stream, cancellable, callback, user_data); - g_task_set_task_data(task, g_bytes_ref(bytes), - (GDestroyNotify)g_bytes_unref); - g_task_set_source_tag(task, purple_queued_output_stream_push_bytes_async); - g_task_set_priority(task, io_priority); - - set_pending = g_output_stream_set_pending(G_OUTPUT_STREAM(stream), &error); - - /* Since we're allowing queuing requests without blocking, - * it's not an error to be pending while processing queued operations. - */ - if(!set_pending && - (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_PENDING) || - !stream->pending_queued)) - { - g_task_return_error(task, error); - g_object_unref(task); - return; - } - - g_clear_error(&error); - stream->pending_queued = TRUE; - - if(set_pending) { - /* Start processing if there were no pending operations */ - purple_queued_output_stream_start_push_bytes_async(task); - } else { - /* Otherwise queue the data */ - g_async_queue_push(stream->queue, task); - } -} - -gboolean -purple_queued_output_stream_push_bytes_finish(PurpleQueuedOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail(PURPLE_IS_QUEUED_OUTPUT_STREAM(stream), FALSE); - g_return_val_if_fail(g_task_is_valid(result, stream), FALSE); - g_return_val_if_fail(g_async_result_is_tagged(result, - purple_queued_output_stream_push_bytes_async), - FALSE); - - return g_task_propagate_boolean(G_TASK(result), error); -} - -void -purple_queued_output_stream_clear_queue(PurpleQueuedOutputStream *stream) { - GTask *task; - - g_return_if_fail(PURPLE_IS_QUEUED_OUTPUT_STREAM(stream)); - - while((task = g_async_queue_try_pop(stream->queue)) != NULL) { - g_task_return_new_error(task, G_IO_ERROR, G_IO_ERROR_CANCELLED, - "PurpleQueuedOutputStream queue cleared"); - g_object_unref(task); - } -}
--- a/libpurple/queuedoutputstream.h Tue Jan 23 01:24:59 2024 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Purple - Internet Messaging Library - * Copyright (C) Pidgin Developers <devel@pidgin.im> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <https://www.gnu.org/licenses/>. - */ - -#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) -# error "only <purple.h> may be included directly" -#endif - -#ifndef PURPLE_QUEUED_OUTPUT_STREAM_H -#define PURPLE_QUEUED_OUTPUT_STREAM_H - -#include <gio/gio.h> - -#include "purpleversion.h" - -G_BEGIN_DECLS - -#define PURPLE_TYPE_QUEUED_OUTPUT_STREAM purple_queued_output_stream_get_type() - -/** - * PurpleQueuedOutputStream: - * - * An implementation of #GFilterOutputStream which allows queuing data for - * output. This allows data to be queued while other data is being output. - * Therefore, data doesn't have to be manually stored while waiting for - * stream operations to finish. - * - * To create a queued output stream, use [ctor@QueuedOutputStream.new]. - * - * To queue data, use [method@QueuedOutputStream.push_bytes_async]. - * - * If there's a fatal stream error, it's suggested to clear the remaining bytes - * queued with [method@QueuedOutputStream.clear_queue] to avoid excessive - * errors returned in [method@QueuedOutputStream.push_bytes_async]'s async - * callback. - * - * Since: 3.0.0 - */ -PURPLE_AVAILABLE_IN_3_0 -G_DECLARE_FINAL_TYPE(PurpleQueuedOutputStream, purple_queued_output_stream, - PURPLE, QUEUED_OUTPUT_STREAM, GFilterOutputStream) - -/** - * purple_queued_output_stream_new: - * @base_stream: Base output stream to wrap with the queued stream - * - * Creates a new queued output stream for a base stream. - * - * Returns: (transfer full): The new stream. - * - * Since: 3.0.0 - */ -PURPLE_AVAILABLE_IN_3_0 -PurpleQueuedOutputStream *purple_queued_output_stream_new(GOutputStream *base_stream); - -/** - * purple_queued_output_stream_push_bytes_async: - * @stream: The instance. - * @bytes: The bytes to queue. - * @priority: IO priority of the request. - * @cancellable: (nullable): A [class@Gio.Cancellable] or %NULL. - * @callback: (scope async): Callback to call when the request is finished. - * @data: (closure): Data to pass to @callback. - * - * Asynchronously queues and then writes data to @stream. Once the data has - * been written, or an error occurs, @callback will be called. - * - * Be careful such that if there's a fatal stream error, all remaining queued - * operations will likely return this error. Use - * [method@Purple.QueuedOutputStream.clear_queue] to clear the queue on such - * an error to only report it a single time. - * - * Since: 3.0.0 - */ -PURPLE_AVAILABLE_IN_3_0 -void purple_queued_output_stream_push_bytes_async(PurpleQueuedOutputStream *stream, GBytes *bytes, int priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); - -/** - * purple_queued_output_stream_push_bytes_finish: - * @stream: The instance. - * @result: The [iface@Gio.AsyncResult] of this operation. - * @error: Return address for a #GError, or %NULL. - * - * Finishes pushing bytes asynchronously. - * - * Returns: %TRUE on success, %FALSE if there was an error - * - * Since: 3.0.0 - */ -PURPLE_AVAILABLE_IN_3_0 -gboolean purple_queued_output_stream_push_bytes_finish(PurpleQueuedOutputStream *stream, GAsyncResult *result, GError **error); - -/** - * purple_queued_output_stream_clear_queue: - * @stream: The instance. - * - * Clears the queue of any pending bytes. However, any bytes that are in the - * process of being sent will finish their operation. - * - * This function is useful for clearing the queue in case of an IO error. Call - * this in the async callback in order to clear the queue and avoid having all - * [method@Purple.QueuedOutputStream.push_bytes_async] calls on @stream return - * errors if there's a fatal stream error. - * - * Since: 3.0.0 - */ -PURPLE_AVAILABLE_IN_3_0 -void purple_queued_output_stream_clear_queue(PurpleQueuedOutputStream *stream); - -G_END_DECLS - -#endif /* PURPLE_QUEUED_OUTPUT_STREAM_H */
--- a/libpurple/tests/meson.build Tue Jan 23 01:24:59 2024 -0600 +++ b/libpurple/tests/meson.build Tue Jan 23 01:34:53 2024 -0600 @@ -35,7 +35,6 @@ 'protocol_roster', 'protocol_xfer', 'purplepath', - 'queued_output_stream', 'request_field', 'request_group', 'request_page',
--- a/libpurple/tests/test_queued_output_stream.c Tue Jan 23 01:24:59 2024 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/* - * Purple - * - * Purple is the legal property of its developers, whose names are too - * numerous to list here. Please refer to the COPYRIGHT file distributed - * with this source distribution - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include <glib.h> -#include <string.h> - -#include <purple.h> - -static const gsize test_bytes_data_len = 5; -static const guint8 test_bytes_data[] = "12345"; - -static const gsize test_bytes_data_len2 = 4; -static const guint8 test_bytes_data2[] = "6789"; - -static const gsize test_bytes_data_len3 = 12; -static const guint8 test_bytes_data3[] = "101112131415"; - -static void -test_queued_output_stream_new(void) { - GOutputStream *output; - PurpleQueuedOutputStream *queued; - GError *err = NULL; - gboolean ret = FALSE; - - output = g_memory_output_stream_new_resizable(); - g_assert_nonnull(output); - - queued = purple_queued_output_stream_new(output); - g_assert_true(PURPLE_IS_QUEUED_OUTPUT_STREAM(queued)); - - ret = g_output_stream_close(G_OUTPUT_STREAM(queued), NULL, &err); - g_assert_no_error(err); - g_assert_true(ret); - - g_clear_object(&queued); - g_clear_object(&output); -} - -static void -test_queued_output_stream_push_bytes_async_cb(GObject *source, - GAsyncResult *res, gpointer user_data) -{ - PurpleQueuedOutputStream *queued = PURPLE_QUEUED_OUTPUT_STREAM(source); - gboolean *done = user_data; - GError *err = NULL; - gboolean ret = FALSE; - - ret = purple_queued_output_stream_push_bytes_finish(queued, res, &err); - g_assert_no_error(err); - g_assert_true(ret); - - *done = TRUE; -} - -static void -test_queued_output_stream_push_bytes_async(void) { - GMemoryOutputStream *output; - PurpleQueuedOutputStream *queued; - GBytes *bytes; - GError *err = NULL; - gboolean done = FALSE, ret = FALSE; - - output = G_MEMORY_OUTPUT_STREAM(g_memory_output_stream_new_resizable()); - g_assert_nonnull(output); - - queued = purple_queued_output_stream_new(G_OUTPUT_STREAM(output)); - g_assert_true(PURPLE_IS_QUEUED_OUTPUT_STREAM(queued)); - - bytes = g_bytes_new_static(test_bytes_data, test_bytes_data_len); - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, NULL, - test_queued_output_stream_push_bytes_async_cb, &done); - g_bytes_unref(bytes); - - while (!done) { - g_main_context_iteration(NULL, TRUE); - } - - g_assert_cmpmem(g_memory_output_stream_get_data(output), - g_memory_output_stream_get_data_size(output), - test_bytes_data, test_bytes_data_len); - - ret = g_output_stream_close(G_OUTPUT_STREAM(queued), NULL, &err); - g_assert_no_error(err); - g_assert_true(ret); - - g_clear_object(&queued); - g_clear_object(&output); -} - -static void -test_queued_output_stream_push_bytes_async_multiple_cb(GObject *source, - GAsyncResult *res, gpointer user_data) -{ - PurpleQueuedOutputStream *queued = PURPLE_QUEUED_OUTPUT_STREAM(source); - gint *done = user_data; - GError *err = NULL; - gboolean ret = FALSE; - - ret = purple_queued_output_stream_push_bytes_finish(queued, res, &err); - g_assert_no_error(err); - g_assert_true(ret); - - --*done; -} - -static void -test_queued_output_stream_push_bytes_async_multiple(void) { - GMemoryOutputStream *output; - PurpleQueuedOutputStream *queued; - GBytes *bytes; - gchar *all_test_bytes_data; - GError *err = NULL; - int done = 3; - gboolean ret = FALSE; - - output = G_MEMORY_OUTPUT_STREAM(g_memory_output_stream_new_resizable()); - g_assert_nonnull(output); - - queued = purple_queued_output_stream_new(G_OUTPUT_STREAM(output)); - g_assert_true(PURPLE_IS_QUEUED_OUTPUT_STREAM(queued)); - - bytes = g_bytes_new_static(test_bytes_data, test_bytes_data_len); - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, NULL, - test_queued_output_stream_push_bytes_async_multiple_cb, - &done); - g_bytes_unref(bytes); - - bytes = g_bytes_new_static(test_bytes_data2, test_bytes_data_len2); - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, NULL, - test_queued_output_stream_push_bytes_async_multiple_cb, - &done); - g_bytes_unref(bytes); - - bytes = g_bytes_new_static(test_bytes_data3, test_bytes_data_len3); - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, NULL, - test_queued_output_stream_push_bytes_async_multiple_cb, - &done); - g_bytes_unref(bytes); - - while (done > 0) { - g_main_context_iteration(NULL, TRUE); - } - - g_assert_cmpint(done, ==, 0); - - all_test_bytes_data = g_strconcat((const gchar *)test_bytes_data, - test_bytes_data2, test_bytes_data3, NULL); - - g_assert_cmpmem(g_memory_output_stream_get_data(output), - g_memory_output_stream_get_data_size(output), - all_test_bytes_data, strlen(all_test_bytes_data)); - - g_free(all_test_bytes_data); - - ret = g_output_stream_close(G_OUTPUT_STREAM(queued), NULL, &err); - g_assert_no_error(err); - g_assert_true(ret); - - g_clear_object(&queued); - g_clear_object(&output); -} - -static void -test_queued_output_stream_push_bytes_async_error_cb(GObject *source, - GAsyncResult *res, gpointer user_data) -{ - PurpleQueuedOutputStream *queued = PURPLE_QUEUED_OUTPUT_STREAM(source); - gint *done = user_data; - GError *err = NULL; - - g_assert_false(purple_queued_output_stream_push_bytes_finish(queued, - res, &err)); - - g_assert_error(err, G_IO_ERROR, G_IO_ERROR_CANCELLED); - g_clear_error(&err); - - --*done; -} - -static void -test_queued_output_stream_push_bytes_async_error(void) { - GMemoryOutputStream *output; - PurpleQueuedOutputStream *queued; - GBytes *bytes; - GCancellable *cancellable; - GError *err = NULL; - gint done = 3; - gboolean ret = FALSE; - - output = G_MEMORY_OUTPUT_STREAM(g_memory_output_stream_new_resizable()); - g_assert_nonnull(output); - - queued = purple_queued_output_stream_new(G_OUTPUT_STREAM(output)); - g_assert_true(PURPLE_IS_QUEUED_OUTPUT_STREAM(queued)); - - cancellable = g_cancellable_new(); - g_assert_nonnull(cancellable); - - g_cancellable_cancel(cancellable); - g_assert_true(g_cancellable_is_cancelled(cancellable)); - - bytes = g_bytes_new_static(test_bytes_data, test_bytes_data_len); - - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, cancellable, - test_queued_output_stream_push_bytes_async_error_cb, - &done); - - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, cancellable, - test_queued_output_stream_push_bytes_async_error_cb, - &done); - - purple_queued_output_stream_push_bytes_async(queued, bytes, - G_PRIORITY_DEFAULT, cancellable, - test_queued_output_stream_push_bytes_async_error_cb, - &done); - - g_bytes_unref(bytes); - - while (done > 0) { - g_main_context_iteration(NULL, TRUE); - } - - g_assert_cmpint(done, ==, 0); - - g_assert_cmpmem(g_memory_output_stream_get_data(output), - g_memory_output_stream_get_data_size(output), - NULL, 0); - - ret = g_output_stream_close(G_OUTPUT_STREAM(queued), NULL, &err); - g_assert_no_error(err); - g_assert_true(ret); - - g_clear_object(&cancellable); - g_clear_object(&queued); - g_clear_object(&output); -} - -/****************************************************************************** - * Main - *****************************************************************************/ -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_set_nonfatal_assertions(); - - g_test_add_func("/queued-output-stream/new", - test_queued_output_stream_new); - g_test_add_func("/queued-output-stream/push-bytes-async", - test_queued_output_stream_push_bytes_async); - g_test_add_func("/queued-output-stream/push-bytes-async-multiple", - test_queued_output_stream_push_bytes_async_multiple); - g_test_add_func("/queued-output-stream/push-bytes-async-error", - test_queued_output_stream_push_bytes_async_error); - - return g_test_run(); -}
--- a/po/POTFILES.in Tue Jan 23 01:24:59 2024 -0600 +++ b/po/POTFILES.in Tue Jan 23 01:34:53 2024 -0600 @@ -187,7 +187,6 @@ libpurple/purplewhiteboard.c libpurple/purplewhiteboardmanager.c libpurple/purplewhiteboarduiops.c -libpurple/queuedoutputstream.c libpurple/request.c libpurple/request-datasheet.c libpurple/request/purplerequestfield.c @@ -222,7 +221,6 @@ libpurple/tests/test_protocol_action.c libpurple/tests/test_protocol_xfer.c libpurple/tests/test_purplepath.c -libpurple/tests/test_queued_output_stream.c libpurple/tests/test_ui.c libpurple/tests/test_util.c libpurple/tests/test_whiteboard_manager.c