From 3b3eadd4252251310b73c0db524b4e23323d0e7d Mon Sep 17 00:00:00 2001 From: Sten Larsson Date: Thu, 4 Dec 2025 23:29:03 +0100 Subject: [PATCH 1/2] Add GArrowZeroFillOptions --- c_glib/arrow-glib/compute.cpp | 176 ++++++++++++++++++++++++++ c_glib/arrow-glib/compute.h | 16 +++ c_glib/arrow-glib/compute.hpp | 5 + c_glib/test/test-zero-fill-options.rb | 48 +++++++ 4 files changed, 245 insertions(+) create mode 100644 c_glib/test/test-zero-fill-options.rb diff --git a/c_glib/arrow-glib/compute.cpp b/c_glib/arrow-glib/compute.cpp index 8a698ab939f..cb3961667ed 100644 --- a/c_glib/arrow-glib/compute.cpp +++ b/c_glib/arrow-glib/compute.cpp @@ -306,6 +306,8 @@ G_BEGIN_DECLS * #GArrowPivotWiderOptions is a class to customize the `pivot_wider` and * `hash_pivot_wider` functions. * + * #GArrowZeroFillOptions is a class to customize the `utf8_zero_fill` function. + * * There are many functions to compute data on an array. */ @@ -8762,6 +8764,157 @@ garrow_pivot_wider_options_new(void) g_object_new(GARROW_TYPE_PIVOT_WIDER_OPTIONS, nullptr)); } +enum { + PROP_ZERO_FILL_OPTIONS_WIDTH = 1, + PROP_ZERO_FILL_OPTIONS_PADDING, +}; + +typedef struct _GArrowZeroFillOptionsPrivate GArrowZeroFillOptionsPrivate; +struct _GArrowZeroFillOptionsPrivate +{ + gchar *padding; +}; + +G_DEFINE_TYPE_WITH_PRIVATE(GArrowZeroFillOptions, + garrow_zero_fill_options, + GARROW_TYPE_FUNCTION_OPTIONS) + +#define GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object) \ + static_cast( \ + garrow_zero_fill_options_get_instance_private(GARROW_ZERO_FILL_OPTIONS(object))) + +static void +garrow_zero_fill_options_dispose(GObject *object) +{ + auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); + if (priv->padding) { + g_free(priv->padding); + priv->padding = nullptr; + } + G_OBJECT_CLASS(garrow_zero_fill_options_parent_class)->dispose(object); +} + +static void +garrow_zero_fill_options_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + auto options = garrow_zero_fill_options_get_raw(GARROW_ZERO_FILL_OPTIONS(object)); + auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_ZERO_FILL_OPTIONS_WIDTH: + options->width = g_value_get_int64(value); + break; + case PROP_ZERO_FILL_OPTIONS_PADDING: + { + const gchar *padding = g_value_get_string(value); + if (priv->padding) { + g_free(priv->padding); + } + priv->padding = g_strdup(padding); + options->padding = padding ? padding : ""; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +garrow_zero_fill_options_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + auto options = garrow_zero_fill_options_get_raw(GARROW_ZERO_FILL_OPTIONS(object)); + auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_ZERO_FILL_OPTIONS_WIDTH: + g_value_set_int64(value, options->width); + break; + case PROP_ZERO_FILL_OPTIONS_PADDING: + g_value_set_string(value, priv->padding ? priv->padding : options->padding.c_str()); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +garrow_zero_fill_options_init(GArrowZeroFillOptions *object) +{ + auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); + priv->padding = nullptr; + auto arrow_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object); + arrow_priv->options = + static_cast(new arrow::compute::ZeroFillOptions()); + // Sync the private string with the C++ options + auto arrow_options = garrow_zero_fill_options_get_raw(GARROW_ZERO_FILL_OPTIONS(object)); + priv->padding = g_strdup(arrow_options->padding.c_str()); +} + +static void +garrow_zero_fill_options_class_init(GArrowZeroFillOptionsClass *klass) +{ + auto gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = garrow_zero_fill_options_dispose; + gobject_class->set_property = garrow_zero_fill_options_set_property; + gobject_class->get_property = garrow_zero_fill_options_get_property; + + arrow::compute::ZeroFillOptions options; + + GParamSpec *spec; + /** + * GArrowZeroFillOptions:width: + * + * The desired string length. + * + * Since: 23.0.0 + */ + spec = g_param_spec_int64("width", + "Width", + "The desired string length", + G_MININT64, + G_MAXINT64, + options.width, + static_cast(G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_ZERO_FILL_OPTIONS_WIDTH, spec); + + /** + * GArrowZeroFillOptions:padding: + * + * What to pad the string with. Should be one codepoint (Unicode). + * + * Since: 23.0.0 + */ + spec = + g_param_spec_string("padding", + "Padding", + "What to pad the string with. Should be one codepoint (Unicode)", + options.padding.c_str(), + static_cast(G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_ZERO_FILL_OPTIONS_PADDING, spec); +} + +/** + * garrow_zero_fill_options_new: + * + * Returns: A newly created #GArrowZeroFillOptions. + * + * Since: 23.0.0 + */ +GArrowZeroFillOptions * +garrow_zero_fill_options_new(void) +{ + return GARROW_ZERO_FILL_OPTIONS(g_object_new(GARROW_TYPE_ZERO_FILL_OPTIONS, NULL)); +} + G_END_DECLS arrow::Result @@ -8981,6 +9134,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt static_cast(arrow_options); auto options = garrow_pivot_wider_options_new_raw(arrow_pivot_wider_options); return GARROW_FUNCTION_OPTIONS(options); + } else if (arrow_type_name == "ZeroFillOptions") { + const auto arrow_zero_fill_options = + static_cast(arrow_options); + auto options = garrow_zero_fill_options_new_raw(arrow_zero_fill_options); + return GARROW_FUNCTION_OPTIONS(options); } else { auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL); return GARROW_FUNCTION_OPTIONS(options); @@ -9870,3 +10028,21 @@ garrow_pivot_wider_options_get_raw(GArrowPivotWiderOptions *options) return static_cast( garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options))); } + +GArrowZeroFillOptions * +garrow_zero_fill_options_new_raw(const arrow::compute::ZeroFillOptions *arrow_options) +{ + return GARROW_ZERO_FILL_OPTIONS(g_object_new(GARROW_TYPE_ZERO_FILL_OPTIONS, + "width", + arrow_options->width, + "padding", + arrow_options->padding.c_str(), + NULL)); +} + +arrow::compute::ZeroFillOptions * +garrow_zero_fill_options_get_raw(GArrowZeroFillOptions *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 53fb5ae7fc8..9836a294380 100644 --- a/c_glib/arrow-glib/compute.h +++ b/c_glib/arrow-glib/compute.h @@ -1540,4 +1540,20 @@ GARROW_AVAILABLE_IN_23_0 GArrowPivotWiderOptions * garrow_pivot_wider_options_new(void); +#define GARROW_TYPE_ZERO_FILL_OPTIONS (garrow_zero_fill_options_get_type()) +GARROW_AVAILABLE_IN_23_0 +G_DECLARE_DERIVABLE_TYPE(GArrowZeroFillOptions, + garrow_zero_fill_options, + GARROW, + ZERO_FILL_OPTIONS, + GArrowFunctionOptions) +struct _GArrowZeroFillOptionsClass +{ + GArrowFunctionOptionsClass parent_class; +}; + +GARROW_AVAILABLE_IN_23_0 +GArrowZeroFillOptions * +garrow_zero_fill_options_new(void); + G_END_DECLS diff --git a/c_glib/arrow-glib/compute.hpp b/c_glib/arrow-glib/compute.hpp index 7b7a11df1bc..dbe5f437867 100644 --- a/c_glib/arrow-glib/compute.hpp +++ b/c_glib/arrow-glib/compute.hpp @@ -274,3 +274,8 @@ garrow_pivot_wider_options_new_raw( const arrow::compute::PivotWiderOptions *arrow_options); arrow::compute::PivotWiderOptions * garrow_pivot_wider_options_get_raw(GArrowPivotWiderOptions *options); + +GArrowZeroFillOptions * +garrow_zero_fill_options_new_raw(const arrow::compute::ZeroFillOptions *arrow_options); +arrow::compute::ZeroFillOptions * +garrow_zero_fill_options_get_raw(GArrowZeroFillOptions *options); diff --git a/c_glib/test/test-zero-fill-options.rb b/c_glib/test/test-zero-fill-options.rb new file mode 100644 index 00000000000..110bb2cf05c --- /dev/null +++ b/c_glib/test/test-zero-fill-options.rb @@ -0,0 +1,48 @@ +# 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 TestZeroFillOptions < Test::Unit::TestCase + include Helper::Buildable + + def setup + @options = Arrow::ZeroFillOptions.new + end + + def test_width_property + assert_equal(0, @options.width) + @options.width = 4 + assert_equal(4, @options.width) + end + + def test_padding_property + assert_equal("0", @options.padding) + @options.padding = "x" + assert_equal("x", @options.padding) + end + + def test_utf8_zero_fill_function + args = [ + Arrow::ArrayDatum.new(build_string_array(["1", "-2", "+3"])), + ] + @options.width = 4 + @options.padding = "0" + utf8_zero_fill_function = Arrow::Function.find("utf8_zero_fill") + result = utf8_zero_fill_function.execute(args, @options).value + expected = build_string_array(["0001", "-002", "+003"]) + assert_equal(expected, result) + end +end From 2b080c039c60da5e2bd8aab57bf70bbca40782d2 Mon Sep 17 00:00:00 2001 From: Sten Larsson Date: Wed, 31 Dec 2025 10:35:33 +0100 Subject: [PATCH 2/2] Remove private struct --- c_glib/arrow-glib/compute.cpp | 46 ++++------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/c_glib/arrow-glib/compute.cpp b/c_glib/arrow-glib/compute.cpp index cb3961667ed..78deb7f6d76 100644 --- a/c_glib/arrow-glib/compute.cpp +++ b/c_glib/arrow-glib/compute.cpp @@ -8769,30 +8769,9 @@ enum { PROP_ZERO_FILL_OPTIONS_PADDING, }; -typedef struct _GArrowZeroFillOptionsPrivate GArrowZeroFillOptionsPrivate; -struct _GArrowZeroFillOptionsPrivate -{ - gchar *padding; -}; - -G_DEFINE_TYPE_WITH_PRIVATE(GArrowZeroFillOptions, - garrow_zero_fill_options, - GARROW_TYPE_FUNCTION_OPTIONS) - -#define GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object) \ - static_cast( \ - garrow_zero_fill_options_get_instance_private(GARROW_ZERO_FILL_OPTIONS(object))) - -static void -garrow_zero_fill_options_dispose(GObject *object) -{ - auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); - if (priv->padding) { - g_free(priv->padding); - priv->padding = nullptr; - } - G_OBJECT_CLASS(garrow_zero_fill_options_parent_class)->dispose(object); -} +G_DEFINE_TYPE(GArrowZeroFillOptions, + garrow_zero_fill_options, + GARROW_TYPE_FUNCTION_OPTIONS) static void garrow_zero_fill_options_set_property(GObject *object, @@ -8801,21 +8780,13 @@ garrow_zero_fill_options_set_property(GObject *object, GParamSpec *pspec) { auto options = garrow_zero_fill_options_get_raw(GARROW_ZERO_FILL_OPTIONS(object)); - auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); switch (prop_id) { case PROP_ZERO_FILL_OPTIONS_WIDTH: options->width = g_value_get_int64(value); break; case PROP_ZERO_FILL_OPTIONS_PADDING: - { - const gchar *padding = g_value_get_string(value); - if (priv->padding) { - g_free(priv->padding); - } - priv->padding = g_strdup(padding); - options->padding = padding ? padding : ""; - } + options->padding = g_value_get_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -8830,14 +8801,13 @@ garrow_zero_fill_options_get_property(GObject *object, GParamSpec *pspec) { auto options = garrow_zero_fill_options_get_raw(GARROW_ZERO_FILL_OPTIONS(object)); - auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); switch (prop_id) { case PROP_ZERO_FILL_OPTIONS_WIDTH: g_value_set_int64(value, options->width); break; case PROP_ZERO_FILL_OPTIONS_PADDING: - g_value_set_string(value, priv->padding ? priv->padding : options->padding.c_str()); + g_value_set_string(value, options->padding.c_str()); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -8848,14 +8818,9 @@ garrow_zero_fill_options_get_property(GObject *object, static void garrow_zero_fill_options_init(GArrowZeroFillOptions *object) { - auto priv = GARROW_ZERO_FILL_OPTIONS_GET_PRIVATE(object); - priv->padding = nullptr; auto arrow_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object); arrow_priv->options = static_cast(new arrow::compute::ZeroFillOptions()); - // Sync the private string with the C++ options - auto arrow_options = garrow_zero_fill_options_get_raw(GARROW_ZERO_FILL_OPTIONS(object)); - priv->padding = g_strdup(arrow_options->padding.c_str()); } static void @@ -8863,7 +8828,6 @@ garrow_zero_fill_options_class_init(GArrowZeroFillOptionsClass *klass) { auto gobject_class = G_OBJECT_CLASS(klass); - gobject_class->dispose = garrow_zero_fill_options_dispose; gobject_class->set_property = garrow_zero_fill_options_set_property; gobject_class->get_property = garrow_zero_fill_options_get_property;