Bug Summary

File:cafevaluearray.c
Warning:line 639, column 35
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cafevaluearray.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -D HAVE_CONFIG_H -I . -I .. -D TERMINAL_COMPILATION -D TERMINAL_RESOURCES_PATH_PREFIX="/org/cafe/terminal" -D TERM_DATADIR="/usr/share" -D TERM_LOCALEDIR="/usr/share/locale" -D TERM_PKGDATADIR="/usr/share/cafe-terminal" -D TERM_HELPDIR="/usr/share/help" -D SN_API_NOT_YET_FROZEN -D CDK_MULTIHEAD_SAFE -D G_DISABLE_SINGLE_INCLUDES -D PANGO_DISABLE_SINGLE_INCLUDES -D ATK_DISABLE_SINGLE_INCLUDES -D CDK_DISABLE_SINGLE_INCLUDES -D CDK_PIXBUF_DISABLE_SINGLE_INCLUDES -D CTK_DISABLE_SINGLE_INCLUDES -D EGG_SM_CLIENT_BACKEND_XSMP -I /usr/local/include/bte-2.91 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/ctk-3.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/dconf -I /usr/include/uuid -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker security.ArrayBound -analyzer-checker unix.cstring.NotNullTerminated -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2026-01-28-103223-19377-1 -x c cafevaluearray.c
1/* LIBCAFE - The CAFE Library
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3 *
4 * cafevaluearray.c ported from GValueArray
5 *
6 * This library is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <https://www.gnu.org/licenses/>.
19 */
20
21#include "config.h"
22
23#include <string.h>
24
25#include <glib-object.h>
26#include <gobject/gvaluecollector.h>
27
28#include "cafevaluearray.h"
29
30
31/**
32 * SECTION:cafevaluearray
33 * @short_description: A container structure to maintain an array of
34 * generic values
35 * @see_also: #GValue, #GParamSpecValueArray, cafe_param_spec_value_array()
36 * @title: CafeValueArray
37 *
38 * The prime purpose of a #CafeValueArray is for it to be used as an
39 * object property that holds an array of values. A #CafeValueArray wraps
40 * an array of #GValue elements in order for it to be used as a boxed
41 * type through %CAFE_TYPE_VALUE_ARRAY.
42 */
43
44
45#define GROUP_N_VALUES(1) (1) /* power of 2 !! */
46
47
48/**
49 * CafeValueArray:
50 *
51 * A #CafeValueArray contains an array of #GValue elements.
52 *
53 * Since: 2.10
54 */
55struct _CafeValueArray
56{
57 gint n_values;
58 GValue *values;
59
60 gint n_prealloced;
61 gint ref_count;
62};
63
64
65G_DEFINE_BOXED_TYPE (CafeValueArray, cafe_value_array,static GType cafe_value_array_get_type_once (void); GType cafe_value_array_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cafe_value_array_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cafe_value_array_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CafeValueArray
* (*do_copy_type) (CafeValueArray *); CafeValueArray * (*do_const_copy_type
) (const CafeValueArray *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CafeValueArray
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CafeValueArray")
, cafe_value_array_ref, cafe_value_array_unref); { {{};} } return
g_define_type_id; }
66 cafe_value_array_ref, cafe_value_array_unref)static GType cafe_value_array_get_type_once (void); GType cafe_value_array_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= cafe_value_array_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType cafe_value_array_get_type_once (
void) { GType (* _g_register_boxed) (const gchar *, union { CafeValueArray
* (*do_copy_type) (CafeValueArray *); CafeValueArray * (*do_const_copy_type
) (const CafeValueArray *); GBoxedCopyFunc do_copy_boxed; } __attribute__
((__transparent_union__)), union { void (* do_free_type) (CafeValueArray
*); GBoxedFreeFunc do_free_boxed; } __attribute__((__transparent_union__
)) ) = g_boxed_type_register_static; GType g_define_type_id =
_g_register_boxed (g_intern_static_string ("CafeValueArray")
, cafe_value_array_ref, cafe_value_array_unref); { {{};} } return
g_define_type_id; }
67
68
69/**
70 * cafe_value_array_index:
71 * @value_array: #CafeValueArray to get a value from
72 * @index: index of the value of interest
73 *
74 * Return a pointer to the value at @index contained in @value_array.
75 *
76 * Returns: (transfer none): pointer to a value at @index in @value_array
77 *
78 * Since: 2.10
79 */
80GValue *
81cafe_value_array_index (const CafeValueArray *value_array,
82 gint index)
83{
84 g_return_val_if_fail (value_array != NULL, NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (((void*)0)); } } while (0)
;
85 g_return_val_if_fail (index < value_array->n_values, NULL)do { if ((index < value_array->n_values)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "index < value_array->n_values"
); return (((void*)0)); } } while (0)
;
86
87 return value_array->values + index;
88}
89
90static inline void
91value_array_grow (CafeValueArray *value_array,
92 gint n_values,
93 gboolean zero_init)
94{
95 g_return_if_fail ((guint) n_values >= (guint) value_array->n_values)do { if (((guint) n_values >= (guint) value_array->n_values
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "(guint) n_values >= (guint) value_array->n_values"
); return; } } while (0)
;
96
97 value_array->n_values = n_values;
98 if (value_array->n_values > value_array->n_prealloced)
99 {
100 gint i = value_array->n_prealloced;
101
102 value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES(1) - 1) & ~(GROUP_N_VALUES(1) - 1);
103 value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced)((GValue *) g_realloc_n (value_array->values, (value_array
->n_prealloced), sizeof (GValue)))
;
104
105 if (!zero_init)
106 i = value_array->n_values;
107
108 memset (value_array->values + i, 0,
109 (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
110 }
111}
112
113static inline void
114value_array_shrink (CafeValueArray *value_array)
115{
116 if (value_array->n_prealloced >= value_array->n_values + GROUP_N_VALUES(1))
117 {
118 value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES(1) - 1) & ~(GROUP_N_VALUES(1) - 1);
119 value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced)((GValue *) g_realloc_n (value_array->values, (value_array
->n_prealloced), sizeof (GValue)))
;
120 }
121}
122
123/**
124 * cafe_value_array_new:
125 * @n_prealloced: number of values to preallocate space for
126 *
127 * Allocate and initialize a new #CafeValueArray, optionally preserve space
128 * for @n_prealloced elements. New arrays always contain 0 elements,
129 * regardless of the value of @n_prealloced.
130 *
131 * Returns: a newly allocated #CafeValueArray with 0 values
132 *
133 * Since: 2.10
134 */
135CafeValueArray *
136cafe_value_array_new (gint n_prealloced)
137{
138 CafeValueArray *value_array = g_slice_new0 (CafeValueArray)((CafeValueArray*) g_slice_alloc0 (sizeof (CafeValueArray)));
139
140 value_array_grow (value_array, n_prealloced, TRUE(!(0)));
141 value_array->n_values = 0;
142 value_array->ref_count = 1;
143
144 return value_array;
145}
146
147/**
148 * cafe_value_array_new_from_types:
149 * @error_msg: return location for an error message.
150 * @first_type: first type in the array, or #G_TYPE_NONE.
151 * @...: the remaining types in the array, terminated by #G_TYPE_NONE
152 *
153 * Allocate and initialize a new #CafeValueArray, and fill it with
154 * values that are given as a list of (#GType, value) pairs,
155 * terminated by #G_TYPE_NONE.
156 *
157 * Returns: (nullable): a newly allocated #CafeValueArray, or %NULL if
158 * an error happened.
159 *
160 * Since: 3.0
161 */
162CafeValueArray *
163cafe_value_array_new_from_types (gchar **error_msg,
164 GType first_type,
165 ...)
166{
167 CafeValueArray *value_array;
168 va_list va_args;
169
170 g_return_val_if_fail (error_msg == NULL || *error_msg == NULL, NULL)do { if ((error_msg == ((void*)0) || *error_msg == ((void*)0)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "error_msg == NULL || *error_msg == NULL"
); return (((void*)0)); } } while (0)
;
171
172 va_start (va_args, first_type)__builtin_va_start(va_args, first_type);
173
174 value_array = cafe_value_array_new_from_types_valist (error_msg,
175 first_type,
176 va_args);
177
178 va_end (va_args)__builtin_va_end(va_args);
179
180 return value_array;
181}
182
183/**
184 * cafe_value_array_new_from_types_valist:
185 * @error_msg: return location for an error message.
186 * @first_type: first type in the array, or #G_TYPE_NONE.
187 * @va_args: a va_list of GTypes and values, terminated by #G_TYPE_NONE
188 *
189 * Allocate and initialize a new #CafeValueArray, and fill it with
190 * @va_args given in the order as passed to
191 * cafe_value_array_new_from_types().
192 *
193 * Returns: (nullable): a newly allocated #CafeValueArray, or %NULL if
194 * an error happened.
195 *
196 * Since: 3.0
197 */
198CafeValueArray *
199cafe_value_array_new_from_types_valist (gchar **error_msg,
200 GType first_type,
201 va_list va_args)
202{
203 CafeValueArray *value_array;
204 GType type;
205
206 g_return_val_if_fail (error_msg == NULL || *error_msg == NULL, NULL)do { if ((error_msg == ((void*)0) || *error_msg == ((void*)0)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "error_msg == NULL || *error_msg == NULL"
); return (((void*)0)); } } while (0)
;
207
208 type = first_type;
209
210 value_array = cafe_value_array_new (type == G_TYPE_NONE((GType) ((1) << (2))) ? 0 : 1);
211
212 while (type != G_TYPE_NONE((GType) ((1) << (2))))
213 {
214 GValue value = G_VALUE_INIT{ 0, { { 0 } } };
215 gchar *my_error = NULL((void*)0);
216
217 g_value_init (&value, type);
218
219 G_VALUE_COLLECT (&value, va_args, G_VALUE_NOCOPY_CONTENTS, &my_error)do { GValue *g_vc_value = (&value); GType g_vc_value_type
= (((GValue*) (g_vc_value))->g_type); GTypeValueTable *g_vc_vtable
= g_type_value_table_peek (g_vc_value_type); if (g_vc_vtable
->value_free) g_vc_vtable->value_free (g_vc_value); memset
(g_vc_value->data, 0, sizeof (g_vc_value->data)); do {
GTypeValueTable *g_vci_vtab; do { GValue *g_vci_val = (&
value); guint g_vci_flags = ((1 << 27)); const gchar *g_vci_collect_format
; GTypeCValue g_vci_cvalues[(8)] = { { 0, }, }; guint g_vci_n_values
= 0; g_vci_vtab = g_type_value_table_peek (g_vc_value_type);
g_vci_collect_format = g_vci_vtab->collect_format; g_vci_val
->g_type = g_vc_value_type; while (*g_vci_collect_format) {
GTypeCValue *g_vci_cvalue = g_vci_cvalues + g_vci_n_values++
; switch (*g_vci_collect_format++) { case G_VALUE_COLLECT_INT
: g_vci_cvalue->v_int = __builtin_va_arg((va_args), gint);
break; case G_VALUE_COLLECT_LONG: g_vci_cvalue->v_long = __builtin_va_arg
((va_args), glong); break; case G_VALUE_COLLECT_INT64: g_vci_cvalue
->v_int64 = __builtin_va_arg((va_args), gint64); break; case
G_VALUE_COLLECT_DOUBLE: g_vci_cvalue->v_double = __builtin_va_arg
((va_args), gdouble); break; case G_VALUE_COLLECT_POINTER: g_vci_cvalue
->v_pointer = __builtin_va_arg((va_args), gpointer); break
; default: do { g_assertion_message_expr (((gchar*) 0), "cafevaluearray.c"
, 219, ((const char*) (__func__)), ((void*)0)); } while (0); }
} *(&my_error) = g_vci_vtab->collect_value (g_vci_val
, g_vci_n_values, g_vci_cvalues, g_vci_flags); } while (0); }
while (0); } while (0)
;
220
221 if (my_error)
222 {
223 if (error_msg)
224 {
225 *error_msg = my_error;
226 }
227 else
228 {
229 g_printerr ("%s: %s", G_STRFUNC((const char*) (__func__)), my_error);
230 g_free (my_error);
231 }
232
233 cafe_value_array_unref (value_array);
234
235 va_end (va_args)__builtin_va_end(va_args);
236
237 return NULL((void*)0);
238 }
239
240 cafe_value_array_append (value_array, &value);
241 g_value_unset (&value);
242
243 type = va_arg (va_args, GType)__builtin_va_arg(va_args, GType);
244 }
245
246 va_end (va_args)__builtin_va_end(va_args);
247
248 return value_array;
249}
250
251/**
252 * cafe_value_array_ref:
253 * @value_array: #CafeValueArray to ref
254 *
255 * Adds a reference to a #CafeValueArray.
256 *
257 * Returns: the same @value_array
258 *
259 * Since: 2.10
260 */
261CafeValueArray *
262cafe_value_array_ref (CafeValueArray *value_array)
263{
264 g_return_val_if_fail (value_array != NULL, NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (((void*)0)); } } while (0)
;
265
266 value_array->ref_count++;
267
268 return value_array;
269}
270
271/**
272 * cafe_value_array_unref:
273 * @value_array: #CafeValueArray to unref
274 *
275 * Unref a #CafeValueArray. If the reference count drops to zero, the
276 * array including its contents are freed.
277 *
278 * Since: 2.10
279 */
280void
281cafe_value_array_unref (CafeValueArray *value_array)
282{
283 g_return_if_fail (value_array != NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return; } } while (0)
;
284
285 value_array->ref_count--;
286
287 if (value_array->ref_count < 1)
288 {
289 gint i;
290
291 for (i = 0; i < value_array->n_values; i++)
292 {
293 GValue *value = value_array->values + i;
294
295 if (G_VALUE_TYPE (value)(((GValue*) (value))->g_type) != 0) /* we allow unset values in the array */
296 g_value_unset (value);
297 }
298
299 g_free (value_array->values);
300 g_slice_free (CafeValueArray, value_array)do { if (1) g_slice_free1 (sizeof (CafeValueArray), (value_array
)); else (void) ((CafeValueArray*) 0 == (value_array)); } while
(0)
;
301 }
302}
303
304gint
305cafe_value_array_length (const CafeValueArray *value_array)
306{
307 g_return_val_if_fail (value_array != NULL, 0)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (0); } } while (0)
;
308
309 return value_array->n_values;
310}
311
312/**
313 * cafe_value_array_prepend:
314 * @value_array: #CafeValueArray to add an element to
315 * @value: (allow-none): #GValue to copy into #CafeValueArray, or %NULL
316 *
317 * Insert a copy of @value as first element of @value_array. If @value is
318 * %NULL, an uninitialized value is prepended.
319 *
320 * Returns: (transfer none): the #CafeValueArray passed in as @value_array
321 *
322 * Since: 2.10
323 */
324CafeValueArray *
325cafe_value_array_prepend (CafeValueArray *value_array,
326 const GValue *value)
327{
328 g_return_val_if_fail (value_array != NULL, NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (((void*)0)); } } while (0)
;
329
330 return cafe_value_array_insert (value_array, 0, value);
331}
332
333/**
334 * cafe_value_array_append:
335 * @value_array: #CafeValueArray to add an element to
336 * @value: (allow-none): #GValue to copy into #CafeValueArray, or %NULL
337 *
338 * Insert a copy of @value as last element of @value_array. If @value is
339 * %NULL, an uninitialized value is appended.
340 *
341 * Returns: (transfer none): the #CafeValueArray passed in as @value_array
342 *
343 * Since: 2.10
344 */
345CafeValueArray *
346cafe_value_array_append (CafeValueArray *value_array,
347 const GValue *value)
348{
349 g_return_val_if_fail (value_array != NULL, NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (((void*)0)); } } while (0)
;
350
351 return cafe_value_array_insert (value_array, value_array->n_values, value);
352}
353
354/**
355 * cafe_value_array_insert:
356 * @value_array: #CafeValueArray to add an element to
357 * @index: insertion position, must be &lt;= cafe_value_array_length()
358 * @value: (allow-none): #GValue to copy into #CafeValueArray, or %NULL
359 *
360 * Insert a copy of @value at specified position into @value_array. If @value
361 * is %NULL, an uninitialized value is inserted.
362 *
363 * Returns: (transfer none): the #CafeValueArray passed in as @value_array
364 *
365 * Since: 2.10
366 */
367CafeValueArray *
368cafe_value_array_insert (CafeValueArray *value_array,
369 gint index,
370 const GValue *value)
371{
372 gint i;
373
374 g_return_val_if_fail (value_array != NULL, NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (((void*)0)); } } while (0)
;
375 g_return_val_if_fail (index <= value_array->n_values, value_array)do { if ((index <= value_array->n_values)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "index <= value_array->n_values"
); return (value_array); } } while (0)
;
376
377 i = value_array->n_values;
378 value_array_grow (value_array, value_array->n_values + 1, FALSE(0));
379
380 if (index + 1 < value_array->n_values)
381 memmove (value_array->values + index + 1, value_array->values + index,
382 (i - index) * sizeof (value_array->values[0]));
383
384 memset (value_array->values + index, 0, sizeof (value_array->values[0]));
385
386 if (value)
387 {
388 g_value_init (value_array->values + index, G_VALUE_TYPE (value)(((GValue*) (value))->g_type));
389 g_value_copy (value, value_array->values + index);
390 }
391
392 return value_array;
393}
394
395/**
396 * cafe_value_array_remove:
397 * @value_array: #CafeValueArray to remove an element from
398 * @index: position of value to remove, which must be less than
399 * cafe_value_array_length()
400 *
401 * Remove the value at position @index from @value_array.
402 *
403 * Returns: (transfer none): the #CafeValueArray passed in as @value_array
404 *
405 * Since: 2.10
406 */
407CafeValueArray *
408cafe_value_array_remove (CafeValueArray *value_array,
409 gint index)
410{
411 g_return_val_if_fail (value_array != NULL, NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return (((void*)0)); } } while (0)
;
412 g_return_val_if_fail (index < value_array->n_values, value_array)do { if ((index < value_array->n_values)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "index < value_array->n_values"
); return (value_array); } } while (0)
;
413
414 if (G_VALUE_TYPE (value_array->values + index)(((GValue*) (value_array->values + index))->g_type) != 0)
415 g_value_unset (value_array->values + index);
416
417 value_array->n_values--;
418
419 if (index < value_array->n_values)
420 memmove (value_array->values + index, value_array->values + index + 1,
421 (value_array->n_values - index) * sizeof (value_array->values[0]));
422
423 value_array_shrink (value_array);
424
425 if (value_array->n_prealloced > value_array->n_values)
426 memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
427
428 return value_array;
429}
430
431void
432cafe_value_array_truncate (CafeValueArray *value_array,
433 gint n_values)
434{
435 gint i;
436
437 g_return_if_fail (value_array != NULL)do { if ((value_array != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "value_array != NULL"
); return; } } while (0)
;
438 g_return_if_fail (n_values > 0 && n_values <= value_array->n_values)do { if ((n_values > 0 && n_values <= value_array
->n_values)) { } else { g_return_if_fail_warning (((gchar*
) 0), ((const char*) (__func__)), "n_values > 0 && n_values <= value_array->n_values"
); return; } } while (0)
;
439
440 for (i = value_array->n_values; i > n_values; i--)
441 cafe_value_array_remove (value_array, i - 1);
442}
443
444
445/*
446 * CAFE_TYPE_PARAM_VALUE_ARRAY
447 */
448
449static void cafe_param_value_array_class_init (GParamSpecClass *klass);
450static void cafe_param_value_array_init (GParamSpec *pspec);
451static void cafe_param_value_array_finalize (GParamSpec *pspec);
452static void cafe_param_value_array_set_default (GParamSpec *pspec,
453 GValue *value);
454static gboolean cafe_param_value_array_validate (GParamSpec *pspec,
455 GValue *value);
456static gint cafe_param_value_array_values_cmp (GParamSpec *pspec,
457 const GValue *value1,
458 const GValue *value2);
459
460GType
461cafe_param_value_array_get_type (void)
462{
463 static GType type = 0;
464
465 if (! type)
466 {
467 const GTypeInfo info =
468 {
469 sizeof (GParamSpecClass),
470 NULL((void*)0), NULL((void*)0),
471 (GClassInitFunc) cafe_param_value_array_class_init,
472 NULL((void*)0), NULL((void*)0),
473 sizeof (CafeParamSpecValueArray),
474 0,
475 (GInstanceInitFunc) cafe_param_value_array_init,
476 NULL((void*)0)
477 };
478
479 type = g_type_register_static (G_TYPE_PARAM_BOXED(g_param_spec_types[16]),
480 "CafeParamValueArray", &info, 0);
481 }
482
483 return type;
484}
485
486
487static void
488cafe_param_value_array_class_init (GParamSpecClass *klass)
489{
490 klass->value_type = CAFE_TYPE_VALUE_ARRAY(cafe_value_array_get_type ());
491 klass->finalize = cafe_param_value_array_finalize;
492 klass->value_set_default = cafe_param_value_array_set_default;
493 klass->value_validate = cafe_param_value_array_validate;
494 klass->values_cmp = cafe_param_value_array_values_cmp;
495}
496
497static void
498cafe_param_value_array_init (GParamSpec *pspec)
499{
500 CafeParamSpecValueArray *aspec = CAFE_PARAM_SPEC_VALUE_ARRAY (pspec)((((CafeParamSpecValueArray*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((pspec)), ((cafe_param_value_array_get_type
()))))))
;
501
502 aspec->element_spec = NULL((void*)0);
503 aspec->fixed_n_elements = 0; /* disable */
504}
505
506static inline guint
507cafe_value_array_ensure_size (CafeValueArray *value_array,
508 gint fixed_n_elements)
509{
510 guint changed = 0;
511
512 if (fixed_n_elements)
513 {
514 while (cafe_value_array_length (value_array) < fixed_n_elements)
515 {
516 cafe_value_array_append (value_array, NULL((void*)0));
517 changed++;
518 }
519
520 while (cafe_value_array_length (value_array) > fixed_n_elements)
521 {
522 cafe_value_array_remove (value_array,
523 cafe_value_array_length (value_array) - 1);
524 changed++;
525 }
526 }
527
528 return changed;
529}
530
531static void
532cafe_param_value_array_finalize (GParamSpec *pspec)
533{
534 CafeParamSpecValueArray *aspec = CAFE_PARAM_SPEC_VALUE_ARRAY (pspec)((((CafeParamSpecValueArray*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((pspec)), ((cafe_param_value_array_get_type
()))))))
;
535 GParamSpecClass *parent_class;
536
537 parent_class = g_type_class_peek (g_type_parent (CAFE_TYPE_PARAM_VALUE_ARRAY(cafe_param_value_array_get_type ())));
538
539 g_clear_pointer (&aspec->element_spec, g_param_spec_unref)do { _Static_assert (sizeof *(&aspec->element_spec) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&aspec->element_spec)) _pp = (&aspec->element_spec
); __typeof__ (*(&aspec->element_spec)) _ptr = *_pp; *
_pp = ((void*)0); if (_ptr) (g_param_spec_unref) (_ptr); } while
(0)
;
540
541 parent_class->finalize (pspec);
542}
543
544static void
545cafe_param_value_array_set_default (GParamSpec *pspec,
546 GValue *value)
547{
548 CafeParamSpecValueArray *aspec = CAFE_PARAM_SPEC_VALUE_ARRAY (pspec)((((CafeParamSpecValueArray*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((pspec)), ((cafe_param_value_array_get_type
()))))))
;
549
550 if (! value->data[0].v_pointer && aspec->fixed_n_elements)
551 value->data[0].v_pointer = cafe_value_array_new (aspec->fixed_n_elements);
552
553 if (value->data[0].v_pointer)
554 {
555 /* g_value_reset (value); already done */
556 cafe_value_array_ensure_size (value->data[0].v_pointer,
557 aspec->fixed_n_elements);
558 }
559}
560
561static gboolean
562cafe_param_value_array_validate (GParamSpec *pspec,
563 GValue *value)
564{
565 CafeParamSpecValueArray *aspec = CAFE_PARAM_SPEC_VALUE_ARRAY (pspec)((((CafeParamSpecValueArray*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((pspec)), ((cafe_param_value_array_get_type
()))))))
;
566 CafeValueArray *value_array = value->data[0].v_pointer;
567 guint changed = 0;
568
569 if (! value->data[0].v_pointer && aspec->fixed_n_elements)
570 value->data[0].v_pointer = cafe_value_array_new (aspec->fixed_n_elements);
571
572 if (value->data[0].v_pointer)
573 {
574 /* ensure array size validity */
575 changed += cafe_value_array_ensure_size (value_array,
576 aspec->fixed_n_elements);
577
578 /* ensure array values validity against a present element spec */
579 if (aspec->element_spec)
580 {
581 GParamSpec *element_spec = aspec->element_spec;
582 gint length = cafe_value_array_length (value_array);
583 gint i;
584
585 for (i = 0; i < length; i++)
586 {
587 GValue *element = cafe_value_array_index (value_array, i);
588
589 /* need to fixup value type, or ensure that the array
590 * value is initialized at all
591 */
592 if (! g_value_type_compatible (G_VALUE_TYPE (element)(((GValue*) (element))->g_type),
593 G_PARAM_SPEC_VALUE_TYPE (element_spec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((element_spec)), (((GType) ((19) << (2))))))))->
value_type)
))
594 {
595 if (G_VALUE_TYPE (element)(((GValue*) (element))->g_type) != 0)
596 g_value_unset (element);
597
598 g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec)(((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((element_spec)), (((GType) ((19) << (2))))))))->
value_type)
);
599 g_param_value_set_default (element_spec, element);
600 changed++;
601 }
602
603 /* validate array value against element_spec */
604 changed += g_param_value_validate (element_spec, element);
605 }
606 }
607 }
608
609 return changed;
610}
611
612static gint
613cafe_param_value_array_values_cmp (GParamSpec *pspec,
614 const GValue *value1,
615 const GValue *value2)
616{
617 CafeParamSpecValueArray *aspec = CAFE_PARAM_SPEC_VALUE_ARRAY (pspec)((((CafeParamSpecValueArray*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((pspec)), ((cafe_param_value_array_get_type
()))))))
;
618 CafeValueArray *value_array1 = value1->data[0].v_pointer;
619 CafeValueArray *value_array2 = value2->data[0].v_pointer;
620 gint length1;
621 gint length2;
622
623 if (!value_array1 || !value_array2)
624 return value_array2 ? -1 : value_array1 != value_array2;
625
626 length1 = cafe_value_array_length (value_array1);
627 length2 = cafe_value_array_length (value_array2);
628
629 if (length1 != length2)
630 {
631 return length1 < length2 ? -1 : 1;
632 }
633 else if (! aspec->element_spec)
634 {
635 /* we need an element specification for comparisons, so there's
636 * not much to compare here, try to at least provide stable
637 * lesser/greater result
638 */
639 return length1 < length2 ? -1 : length1 > length2;
This statement is never executed
640 }
641 else /* length1 == length2 */
642 {
643 gint i;
644
645 for (i = 0; i < length1; i++)
646 {
647 GValue *element1 = cafe_value_array_index (value_array1, i);
648 GValue *element2 = cafe_value_array_index (value_array2, i);
649 gint cmp;
650
651 /* need corresponding element types, provide stable result
652 * otherwise
653 */
654 if (G_VALUE_TYPE (element1)(((GValue*) (element1))->g_type) != G_VALUE_TYPE (element2)(((GValue*) (element2))->g_type))
655 return G_VALUE_TYPE (element1)(((GValue*) (element1))->g_type) < G_VALUE_TYPE (element2)(((GValue*) (element2))->g_type) ? -1 : 1;
656
657 cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
658 if (cmp)
659 return cmp;
660 }
661
662 return 0;
663 }
664}
665
666/**
667 * cafe_param_spec_value_array:
668 * @name: Canonical name of the property specified.
669 * @nick: Nick name of the property specified.
670 * @blurb: Description of the property specified.
671 * @element_spec: (nullable): #GParamSpec the contained array's elements
672 * have comply to, or %NULL.
673 * @flags: Flags for the property specified.
674 *
675 * Creates a new #CafeParamSpecValueArray specifying a
676 * #G_TYPE_VALUE_ARRAY property.
677 *
678 * See g_param_spec_internal() for details on property names.
679 *
680 * Returns: (transfer full): The newly created #CafeParamSpecValueArray.
681 *
682 * Since: 3.0
683 **/
684GParamSpec *
685cafe_param_spec_value_array (const gchar *name,
686 const gchar *nick,
687 const gchar *blurb,
688 GParamSpec *element_spec,
689 GParamFlags flags)
690{
691 CafeParamSpecValueArray *aspec;
692
693 if (element_spec)
694 g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL)do { if (((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((element_spec)), (((GType) ((19) << (2)))))))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "G_IS_PARAM_SPEC (element_spec)"); return (((void
*)0)); } } while (0)
;
695
696 aspec = g_param_spec_internal (CAFE_TYPE_PARAM_VALUE_ARRAY(cafe_param_value_array_get_type ()),
697 name,
698 nick,
699 blurb,
700 flags);
701 if (element_spec)
702 {
703 aspec->element_spec = g_param_spec_ref (element_spec);
704 g_param_spec_sink (element_spec);
705 }
706
707 return G_PARAM_SPEC (aspec)((((GParamSpec*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((aspec)), (((GType) ((19) << (2))))))))
;
708}
709