From 0855968727f56bc2d33ce32e38aa5a08c6f50a53 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 9 May 2024 15:03:55 +0000 Subject: [PATCH] Add g_converter_convert_bytes Add a utility api to apply a GConverter to data in memory. Test included. --- gio/gconverter.c | 48 ++++++++++++++++++++++++++++++ gio/gconverter.h | 5 ++++ gio/tests/converter.c | 68 +++++++++++++++++++++++++++++++++++++++++++ gio/tests/meson.build | 1 + 4 files changed, 122 insertions(+) create mode 100644 gio/tests/converter.c diff --git a/gio/gconverter.c b/gio/gconverter.c index 973224fd1..b5417744d 100644 --- a/gio/gconverter.c +++ b/gio/gconverter.c @@ -23,6 +23,9 @@ #include "config.h" #include "gconverter.h" #include "glibintl.h" +#include "gmemoryinputstream.h" +#include "gmemoryoutputstream.h" +#include "gconverteroutputstream.h" /** @@ -207,3 +210,48 @@ g_converter_reset (GConverter *converter) (* iface->reset) (converter); } + +/** + * g_converter_convert_bytes: + * @converter: the `GConverter` to use + * @bytes: the data to convert + * @error: location to store the error occurring + * + * Applies @converter to the data in @bytes. + * + * Returns: (transfer full): A newly-allocated + * `GBytes` with the converted data, or `NULL` if an error + * occurred + * + * Since: 2.82 + */ +GBytes * +g_converter_convert_bytes (GConverter *converter, + GBytes *bytes, + GError **error) +{ + GInputStream *input; + GOutputStream *output; + GOutputStream *conv; + GOutputStreamSpliceFlags flags; + GBytes *result = NULL; + + g_converter_reset (converter); + + input = g_memory_input_stream_new_from_bytes (bytes); + output = g_memory_output_stream_new_resizable (); + conv = g_converter_output_stream_new (output, converter); + + flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET; + + if (g_output_stream_splice (conv, input, flags, NULL, error) != -1) + { + result = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output)); + } + + g_object_unref (conv); + g_object_unref (output); + g_object_unref (input); + + return result; +} diff --git a/gio/gconverter.h b/gio/gconverter.h index 87afbf3b6..2ec9440d8 100644 --- a/gio/gconverter.h +++ b/gio/gconverter.h @@ -84,6 +84,11 @@ GConverterResult g_converter_convert (GConverter *converter, GIO_AVAILABLE_IN_ALL void g_converter_reset (GConverter *converter); +GIO_AVAILABLE_IN_2_82 +GBytes * g_converter_convert_bytes (GConverter *converter, + GBytes *bytes, + GError **error); + G_END_DECLS diff --git a/gio/tests/converter.c b/gio/tests/converter.c new file mode 100644 index 000000000..3795a5d09 --- /dev/null +++ b/gio/tests/converter.c @@ -0,0 +1,68 @@ +/* GLib testing framework examples and tests + * Copyright (C) 2024 Red Hat, Inc. + * Authors: Matthias Clasen + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include +#include +#include +#include + + +static void +test_convert_bytes (void) +{ + char data[8192]; + GBytes *bytes; + GConverter *converter; + GError *error = NULL; + GBytes *result; + + for (gsize i = 0; i < sizeof (data); i++) + data[i] = g_test_rand_int_range (0, 256); + + bytes = g_bytes_new_static (data, sizeof (data)); + + converter = G_CONVERTER (g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, 9)); + result = g_converter_convert_bytes (converter, bytes, &error); + g_assert_no_error (error); + g_assert_nonnull (result); + + g_bytes_unref (result); + g_object_unref (converter); + + converter = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP)); + result = g_converter_convert_bytes (converter, bytes, &error); + g_assert_nonnull (error); + g_error_free (error); + g_assert_true (result == NULL); + + g_object_unref (converter); + g_bytes_unref (bytes); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/converter/bytes", test_convert_bytes); + + return g_test_run(); +} diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 3bfb33307..d6b7f26d5 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -70,6 +70,7 @@ gio_tests = { # "LC_COLLATE support for collation orders other than simple codepoint order" 'can_fail' : linux_libc == 'musl', }, + 'converter' : {}, 'credentials' : {}, 'data-input-stream' : {}, 'data-output-stream' : {},