From 00afd88bacfe98257d7ef100536f808c9232532d Mon Sep 17 00:00:00 2001 From: Sten Larsson Date: Thu, 4 Dec 2025 17:52:52 +0100 Subject: [PATCH 1/2] Add GArrowReplaceSliceOptions --- c_glib/arrow-glib/compute.cpp | 211 ++++++++++++++++++++++ c_glib/arrow-glib/compute.h | 16 ++ c_glib/arrow-glib/compute.hpp | 6 + c_glib/test/test-replace-slice-options.rb | 55 ++++++ 4 files changed, 288 insertions(+) create mode 100644 c_glib/test/test-replace-slice-options.rb diff --git a/c_glib/arrow-glib/compute.cpp b/c_glib/arrow-glib/compute.cpp index df6fab4f305..e2c7158ec4d 100644 --- a/c_glib/arrow-glib/compute.cpp +++ b/c_glib/arrow-glib/compute.cpp @@ -296,6 +296,9 @@ G_BEGIN_DECLS * #GArrowPairwiseOptions is a class to customize the pairwise * functions such as `pairwise_diff` and `pairwise_diff_checked`. * + * #GArrowReplaceSliceOptions is a class to customize the `utf8_replace_slice` and + * `binary_replace_slice` functions. + * * There are many functions to compute data on an array. */ @@ -8349,6 +8352,188 @@ garrow_pairwise_options_new(void) return GARROW_PAIRWISE_OPTIONS(g_object_new(GARROW_TYPE_PAIRWISE_OPTIONS, NULL)); } +enum { + PROP_REPLACE_SLICE_OPTIONS_START = 1, + PROP_REPLACE_SLICE_OPTIONS_STOP, + PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT, +}; + +typedef struct _GArrowReplaceSliceOptionsPrivate GArrowReplaceSliceOptionsPrivate; +struct _GArrowReplaceSliceOptionsPrivate +{ + gchar *replacement; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(GArrowReplaceSliceOptions, + garrow_replace_slice_options, + GARROW_TYPE_FUNCTION_OPTIONS) + +#define GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object) \ + static_cast( \ + garrow_replace_slice_options_get_instance_private( \ + GARROW_REPLACE_SLICE_OPTIONS(object))) + +static void +garrow_replace_slice_options_dispose(GObject *object) +{ + auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); + if (priv->replacement) { + g_free(priv->replacement); + priv->replacement = nullptr; + } + G_OBJECT_CLASS(garrow_replace_slice_options_parent_class)->dispose(object); +} + +static void +garrow_replace_slice_options_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + auto options = + garrow_replace_slice_options_get_raw(GARROW_REPLACE_SLICE_OPTIONS(object)); + auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_REPLACE_SLICE_OPTIONS_START: + options->start = g_value_get_int64(value); + break; + case PROP_REPLACE_SLICE_OPTIONS_STOP: + options->stop = g_value_get_int64(value); + break; + case PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT: + { + const gchar *replacement = g_value_get_string(value); + if (priv->replacement) { + g_free(priv->replacement); + } + priv->replacement = g_strdup(replacement); + options->replacement = replacement ? replacement : ""; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +garrow_replace_slice_options_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + auto options = + garrow_replace_slice_options_get_raw(GARROW_REPLACE_SLICE_OPTIONS(object)); + auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_REPLACE_SLICE_OPTIONS_START: + g_value_set_int64(value, options->start); + break; + case PROP_REPLACE_SLICE_OPTIONS_STOP: + g_value_set_int64(value, options->stop); + break; + case PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT: + g_value_set_string(value, + priv->replacement ? priv->replacement + : options->replacement.c_str()); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +garrow_replace_slice_options_init(GArrowReplaceSliceOptions *object) +{ + auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); + priv->replacement = nullptr; + auto arrow_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object); + arrow_priv->options = static_cast( + new arrow::compute::ReplaceSliceOptions()); + // Sync the private replacement string with the C++ options + auto arrow_options = + garrow_replace_slice_options_get_raw(GARROW_REPLACE_SLICE_OPTIONS(object)); + priv->replacement = g_strdup(arrow_options->replacement.c_str()); +} + +static void +garrow_replace_slice_options_class_init(GArrowReplaceSliceOptionsClass *klass) +{ + auto gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = garrow_replace_slice_options_dispose; + gobject_class->set_property = garrow_replace_slice_options_set_property; + gobject_class->get_property = garrow_replace_slice_options_get_property; + + arrow::compute::ReplaceSliceOptions options; + + GParamSpec *spec; + /** + * GArrowReplaceSliceOptions:start: + * + * Index to start slicing at. + * + * Since: 23.0.0 + */ + spec = g_param_spec_int64("start", + "Start", + "Index to start slicing at", + G_MININT64, + G_MAXINT64, + options.start, + static_cast(G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_REPLACE_SLICE_OPTIONS_START, spec); + + /** + * GArrowReplaceSliceOptions:stop: + * + * Index to stop slicing at. + * + * Since: 23.0.0 + */ + spec = g_param_spec_int64("stop", + "Stop", + "Index to stop slicing at", + G_MININT64, + G_MAXINT64, + options.stop, + static_cast(G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_REPLACE_SLICE_OPTIONS_STOP, spec); + + /** + * GArrowReplaceSliceOptions:replacement: + * + * String to replace the slice with. + * + * Since: 23.0.0 + */ + spec = g_param_spec_string("replacement", + "Replacement", + "String to replace the slice with", + options.replacement.c_str(), + static_cast(G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, + PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT, + spec); +} + +/** + * garrow_replace_slice_options_new: + * + * Returns: A newly created #GArrowReplaceSliceOptions. + * + * Since: 23.0.0 + */ +GArrowReplaceSliceOptions * +garrow_replace_slice_options_new(void) +{ + return GARROW_REPLACE_SLICE_OPTIONS( + g_object_new(GARROW_TYPE_REPLACE_SLICE_OPTIONS, NULL)); +} + G_END_DECLS arrow::Result @@ -8553,6 +8738,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt static_cast(arrow_options); auto options = garrow_pairwise_options_new_raw(arrow_pairwise_options); return GARROW_FUNCTION_OPTIONS(options); + } else if (arrow_type_name == "ReplaceSliceOptions") { + const auto arrow_replace_slice_options = + static_cast(arrow_options); + auto options = garrow_replace_slice_options_new_raw(arrow_replace_slice_options); + return GARROW_FUNCTION_OPTIONS(options); } else { auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL); return GARROW_FUNCTION_OPTIONS(options); @@ -9377,3 +9567,24 @@ garrow_pairwise_options_get_raw(GArrowPairwiseOptions *options) return static_cast( garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options))); } + +GArrowReplaceSliceOptions * +garrow_replace_slice_options_new_raw( + const arrow::compute::ReplaceSliceOptions *arrow_options) +{ + return GARROW_REPLACE_SLICE_OPTIONS(g_object_new(GARROW_TYPE_REPLACE_SLICE_OPTIONS, + "start", + arrow_options->start, + "stop", + arrow_options->stop, + "replacement", + arrow_options->replacement.c_str(), + NULL)); +} + +arrow::compute::ReplaceSliceOptions * +garrow_replace_slice_options_get_raw(GArrowReplaceSliceOptions *options) +{ + return static_cast( + garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options))); +} diff --git a/c_glib/arrow-glib/compute.h b/c_glib/arrow-glib/compute.h index becdaf3a672..e5315a07caa 100644 --- a/c_glib/arrow-glib/compute.h +++ b/c_glib/arrow-glib/compute.h @@ -1475,4 +1475,20 @@ GARROW_AVAILABLE_IN_23_0 GArrowPairwiseOptions * garrow_pairwise_options_new(void); +#define GARROW_TYPE_REPLACE_SLICE_OPTIONS (garrow_replace_slice_options_get_type()) +GARROW_AVAILABLE_IN_23_0 +G_DECLARE_DERIVABLE_TYPE(GArrowReplaceSliceOptions, + garrow_replace_slice_options, + GARROW, + REPLACE_SLICE_OPTIONS, + GArrowFunctionOptions) +struct _GArrowReplaceSliceOptionsClass +{ + GArrowFunctionOptionsClass parent_class; +}; + +GARROW_AVAILABLE_IN_23_0 +GArrowReplaceSliceOptions * +garrow_replace_slice_options_new(void); + G_END_DECLS diff --git a/c_glib/arrow-glib/compute.hpp b/c_glib/arrow-glib/compute.hpp index 1a9da1c00c5..bb07bc764ca 100644 --- a/c_glib/arrow-glib/compute.hpp +++ b/c_glib/arrow-glib/compute.hpp @@ -256,3 +256,9 @@ GArrowPairwiseOptions * garrow_pairwise_options_new_raw(const arrow::compute::PairwiseOptions *arrow_options); arrow::compute::PairwiseOptions * garrow_pairwise_options_get_raw(GArrowPairwiseOptions *options); + +GArrowReplaceSliceOptions * +garrow_replace_slice_options_new_raw( + const arrow::compute::ReplaceSliceOptions *arrow_options); +arrow::compute::ReplaceSliceOptions * +garrow_replace_slice_options_get_raw(GArrowReplaceSliceOptions *options); diff --git a/c_glib/test/test-replace-slice-options.rb b/c_glib/test/test-replace-slice-options.rb new file mode 100644 index 00000000000..1cfce27a591 --- /dev/null +++ b/c_glib/test/test-replace-slice-options.rb @@ -0,0 +1,55 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +class TestReplaceSliceOptions < Test::Unit::TestCase + include Helper::Buildable + + def setup + @options = Arrow::ReplaceSliceOptions.new + end + + def test_start_property + assert_equal(0, @options.start) + @options.start = 1 + assert_equal(1, @options.start) + end + + def test_stop_property + assert_equal(0, @options.stop) + @options.stop = 2 + assert_equal(2, @options.stop) + end + + def test_replacement_property + assert_equal("", @options.replacement) + @options.replacement = "XX" + assert_equal("XX", @options.replacement) + end + + def test_utf8_replace_slice_function + args = [ + Arrow::ArrayDatum.new(build_string_array(["hello", "world"])), + ] + @options.start = 1 + @options.stop = 3 + @options.replacement = "XX" + utf8_replace_slice_function = Arrow::Function.find("utf8_replace_slice") + result = utf8_replace_slice_function.execute(args, @options).value + expected = build_string_array(["hXXlo", "wXXld"]) + assert_equal(expected, result) + end +end From 4230f0e0f3ad18ba922e961e4ea70a02fc701ad9 Mon Sep 17 00:00:00 2001 From: Sten Larsson Date: Sat, 27 Dec 2025 11:46:14 +0100 Subject: [PATCH 2/2] Remove priv->replacement --- c_glib/arrow-glib/compute.cpp | 50 ++++------------------------------- 1 file changed, 5 insertions(+), 45 deletions(-) diff --git a/c_glib/arrow-glib/compute.cpp b/c_glib/arrow-glib/compute.cpp index e2c7158ec4d..f4523b69180 100644 --- a/c_glib/arrow-glib/compute.cpp +++ b/c_glib/arrow-glib/compute.cpp @@ -8358,31 +8358,9 @@ enum { PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT, }; -typedef struct _GArrowReplaceSliceOptionsPrivate GArrowReplaceSliceOptionsPrivate; -struct _GArrowReplaceSliceOptionsPrivate -{ - gchar *replacement; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(GArrowReplaceSliceOptions, - garrow_replace_slice_options, - GARROW_TYPE_FUNCTION_OPTIONS) - -#define GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object) \ - static_cast( \ - garrow_replace_slice_options_get_instance_private( \ - GARROW_REPLACE_SLICE_OPTIONS(object))) - -static void -garrow_replace_slice_options_dispose(GObject *object) -{ - auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); - if (priv->replacement) { - g_free(priv->replacement); - priv->replacement = nullptr; - } - G_OBJECT_CLASS(garrow_replace_slice_options_parent_class)->dispose(object); -} +G_DEFINE_TYPE(GArrowReplaceSliceOptions, + garrow_replace_slice_options, + GARROW_TYPE_FUNCTION_OPTIONS) static void garrow_replace_slice_options_set_property(GObject *object, @@ -8392,7 +8370,6 @@ garrow_replace_slice_options_set_property(GObject *object, { auto options = garrow_replace_slice_options_get_raw(GARROW_REPLACE_SLICE_OPTIONS(object)); - auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); switch (prop_id) { case PROP_REPLACE_SLICE_OPTIONS_START: @@ -8402,14 +8379,7 @@ garrow_replace_slice_options_set_property(GObject *object, options->stop = g_value_get_int64(value); break; case PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT: - { - const gchar *replacement = g_value_get_string(value); - if (priv->replacement) { - g_free(priv->replacement); - } - priv->replacement = g_strdup(replacement); - options->replacement = replacement ? replacement : ""; - } + options->replacement = g_value_get_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -8425,7 +8395,6 @@ garrow_replace_slice_options_get_property(GObject *object, { auto options = garrow_replace_slice_options_get_raw(GARROW_REPLACE_SLICE_OPTIONS(object)); - auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); switch (prop_id) { case PROP_REPLACE_SLICE_OPTIONS_START: @@ -8435,9 +8404,7 @@ garrow_replace_slice_options_get_property(GObject *object, g_value_set_int64(value, options->stop); break; case PROP_REPLACE_SLICE_OPTIONS_REPLACEMENT: - g_value_set_string(value, - priv->replacement ? priv->replacement - : options->replacement.c_str()); + g_value_set_string(value, options->replacement.c_str()); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -8448,15 +8415,9 @@ garrow_replace_slice_options_get_property(GObject *object, static void garrow_replace_slice_options_init(GArrowReplaceSliceOptions *object) { - auto priv = GARROW_REPLACE_SLICE_OPTIONS_GET_PRIVATE(object); - priv->replacement = nullptr; auto arrow_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object); arrow_priv->options = static_cast( new arrow::compute::ReplaceSliceOptions()); - // Sync the private replacement string with the C++ options - auto arrow_options = - garrow_replace_slice_options_get_raw(GARROW_REPLACE_SLICE_OPTIONS(object)); - priv->replacement = g_strdup(arrow_options->replacement.c_str()); } static void @@ -8464,7 +8425,6 @@ garrow_replace_slice_options_class_init(GArrowReplaceSliceOptionsClass *klass) { auto gobject_class = G_OBJECT_CLASS(klass); - gobject_class->dispose = garrow_replace_slice_options_dispose; gobject_class->set_property = garrow_replace_slice_options_set_property; gobject_class->get_property = garrow_replace_slice_options_get_property;