mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-11 11:56:16 +01:00
ee247c0a2d
GArray supports a "zero_terminated" flag, but GPtrArray doesn't. This is odd, because especially for a pointer array it makes sense to have a %NULL sentinel. This would be for example useful to track or construct a strv array with a GPtrArray. As workaround for this missing feature you could use a GArray instead (ugly) or to explicitly add the %NULL element. However the latter increases the "len" of the array, which can be problematic if you want to still use the GPtrArray for other purposes. Add API for marking a GPtrArray as %NULL terminated. In that case, the API will ensure that there is always a valid %NULL sentinel after the array. Note that the API does not enforce that a %NULL terminated API actually has any data allocated. That means, even with a %NULL terminated array, pdata can still be %NULL (only if len is zero). Add g_ptr_array_new_null_terminated() constructor. The null-terminated flag cannot be cleared. Once the GPtrArray is flagged to be %NULL terminated, it sticks. The purpose is that once a user checks whether a GPtrArray instance is safe to be treated as a %NULL terminated array, the decision does not need to be re-evaluated. Also add a g_ptr_array_is_null_terminated(). That is useful because it allows you to check whether a GPtrArray created by somebody else is safe to use as a %NULL terminated array. Since there is no API to make an array not %NULL terminated anymore, this is not error prone. The new flag is tracked as a guint8 in GRealPtrArray. On common 64 bit architectures this does not increase the size of the struct as it fits in an existing hole. Note that this is not a bitfield because it's probably more efficient to access the entire guint8. However, there is still a 3 bytes hole (on common 32 and 64 architectures), so if we need to add more flags in the future, we still have space for 24 bits, despite the new flag not being a bitfield. The biggest downside of the patch is the runtime overhead that most operations now need to check whether %NULL termination is requested. Includes some tweaks and additional tests by Philip Withnall. https://gitlab.gnome.org/GNOME/glib/-/issues/353
290 lines
12 KiB
C
290 lines
12 KiB
C
/* GLIB - Library of useful routines for C programming
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
|
* file for a list of people on the GLib Team. See the ChangeLog
|
|
* files for a list of changes. These files are distributed with
|
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
|
*/
|
|
|
|
#ifndef __G_ARRAY_H__
|
|
#define __G_ARRAY_H__
|
|
|
|
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
|
#error "Only <glib.h> can be included directly."
|
|
#endif
|
|
|
|
#include <glib/gtypes.h>
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
typedef struct _GBytes GBytes;
|
|
typedef struct _GArray GArray;
|
|
typedef struct _GByteArray GByteArray;
|
|
typedef struct _GPtrArray GPtrArray;
|
|
|
|
struct _GArray
|
|
{
|
|
gchar *data;
|
|
guint len;
|
|
};
|
|
|
|
struct _GByteArray
|
|
{
|
|
guint8 *data;
|
|
guint len;
|
|
};
|
|
|
|
struct _GPtrArray
|
|
{
|
|
gpointer *pdata;
|
|
guint len;
|
|
};
|
|
|
|
/* Resizable arrays. remove fills any cleared spot and shortens the
|
|
* array, while preserving the order. remove_fast will distort the
|
|
* order by moving the last element to the position of the removed.
|
|
*/
|
|
|
|
#define g_array_append_val(a,v) g_array_append_vals (a, &(v), 1)
|
|
#define g_array_prepend_val(a,v) g_array_prepend_vals (a, &(v), 1)
|
|
#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &(v), 1)
|
|
#define g_array_index(a,t,i) (((t*) (void *) (a)->data) [(i)])
|
|
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_new (gboolean zero_terminated,
|
|
gboolean clear_,
|
|
guint element_size);
|
|
GLIB_AVAILABLE_IN_2_64
|
|
gpointer g_array_steal (GArray *array,
|
|
gsize *len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_sized_new (gboolean zero_terminated,
|
|
gboolean clear_,
|
|
guint element_size,
|
|
guint reserved_size);
|
|
GLIB_AVAILABLE_IN_2_62
|
|
GArray* g_array_copy (GArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
gchar* g_array_free (GArray *array,
|
|
gboolean free_segment);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray *g_array_ref (GArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_array_unref (GArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
guint g_array_get_element_size (GArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_append_vals (GArray *array,
|
|
gconstpointer data,
|
|
guint len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_prepend_vals (GArray *array,
|
|
gconstpointer data,
|
|
guint len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_insert_vals (GArray *array,
|
|
guint index_,
|
|
gconstpointer data,
|
|
guint len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_set_size (GArray *array,
|
|
guint length);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_remove_index (GArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_remove_index_fast (GArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GArray* g_array_remove_range (GArray *array,
|
|
guint index_,
|
|
guint length);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_array_sort (GArray *array,
|
|
GCompareFunc compare_func);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_array_sort_with_data (GArray *array,
|
|
GCompareDataFunc compare_func,
|
|
gpointer user_data);
|
|
GLIB_AVAILABLE_IN_2_62
|
|
gboolean g_array_binary_search (GArray *array,
|
|
gconstpointer target,
|
|
GCompareFunc compare_func,
|
|
guint *out_match_index);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_array_set_clear_func (GArray *array,
|
|
GDestroyNotify clear_func);
|
|
|
|
/* Resizable pointer array. This interface is much less complicated
|
|
* than the above. Add appends a pointer. Remove fills any cleared
|
|
* spot and shortens the array. remove_fast will again distort order.
|
|
*/
|
|
#define g_ptr_array_index(array,index_) ((array)->pdata)[index_]
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GPtrArray* g_ptr_array_new (void);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func);
|
|
GLIB_AVAILABLE_IN_2_64
|
|
gpointer* g_ptr_array_steal (GPtrArray *array,
|
|
gsize *len);
|
|
GLIB_AVAILABLE_IN_2_62
|
|
GPtrArray *g_ptr_array_copy (GPtrArray *array,
|
|
GCopyFunc func,
|
|
gpointer user_data);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GPtrArray* g_ptr_array_new_full (guint reserved_size,
|
|
GDestroyNotify element_free_func);
|
|
GLIB_AVAILABLE_IN_2_74
|
|
GPtrArray* g_ptr_array_new_null_terminated (guint reserved_size,
|
|
GDestroyNotify element_free_func,
|
|
gboolean null_terminated);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
gpointer* g_ptr_array_free (GPtrArray *array,
|
|
gboolean free_seg);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GPtrArray* g_ptr_array_ref (GPtrArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_unref (GPtrArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_set_free_func (GPtrArray *array,
|
|
GDestroyNotify element_free_func);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_set_size (GPtrArray *array,
|
|
gint length);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_2_58
|
|
gpointer g_ptr_array_steal_index (GPtrArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_2_58
|
|
gpointer g_ptr_array_steal_index_fast (GPtrArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
gboolean g_ptr_array_remove (GPtrArray *array,
|
|
gpointer data);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
gboolean g_ptr_array_remove_fast (GPtrArray *array,
|
|
gpointer data);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GPtrArray *g_ptr_array_remove_range (GPtrArray *array,
|
|
guint index_,
|
|
guint length);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_add (GPtrArray *array,
|
|
gpointer data);
|
|
GLIB_AVAILABLE_IN_2_62
|
|
void g_ptr_array_extend (GPtrArray *array_to_extend,
|
|
GPtrArray *array,
|
|
GCopyFunc func,
|
|
gpointer user_data);
|
|
GLIB_AVAILABLE_IN_2_62
|
|
void g_ptr_array_extend_and_steal (GPtrArray *array_to_extend,
|
|
GPtrArray *array);
|
|
GLIB_AVAILABLE_IN_2_40
|
|
void g_ptr_array_insert (GPtrArray *array,
|
|
gint index_,
|
|
gpointer data);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_sort (GPtrArray *array,
|
|
GCompareFunc compare_func);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_sort_with_data (GPtrArray *array,
|
|
GCompareDataFunc compare_func,
|
|
gpointer user_data);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_ptr_array_foreach (GPtrArray *array,
|
|
GFunc func,
|
|
gpointer user_data);
|
|
GLIB_AVAILABLE_IN_2_54
|
|
gboolean g_ptr_array_find (GPtrArray *haystack,
|
|
gconstpointer needle,
|
|
guint *index_);
|
|
GLIB_AVAILABLE_IN_2_54
|
|
gboolean g_ptr_array_find_with_equal_func (GPtrArray *haystack,
|
|
gconstpointer needle,
|
|
GEqualFunc equal_func,
|
|
guint *index_);
|
|
|
|
GLIB_AVAILABLE_IN_2_74
|
|
gboolean g_ptr_array_is_null_terminated (GPtrArray *array);
|
|
|
|
/* Byte arrays, an array of guint8. Implemented as a GArray,
|
|
* but type-safe.
|
|
*/
|
|
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_new (void);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_new_take (guint8 *data,
|
|
gsize len);
|
|
GLIB_AVAILABLE_IN_2_64
|
|
guint8* g_byte_array_steal (GByteArray *array,
|
|
gsize *len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
guint8* g_byte_array_free (GByteArray *array,
|
|
gboolean free_segment);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GBytes* g_byte_array_free_to_bytes (GByteArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray *g_byte_array_ref (GByteArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_byte_array_unref (GByteArray *array);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_append (GByteArray *array,
|
|
const guint8 *data,
|
|
guint len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_prepend (GByteArray *array,
|
|
const guint8 *data,
|
|
guint len);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_set_size (GByteArray *array,
|
|
guint length);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
|
guint index_);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
GByteArray* g_byte_array_remove_range (GByteArray *array,
|
|
guint index_,
|
|
guint length);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_byte_array_sort (GByteArray *array,
|
|
GCompareFunc compare_func);
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_byte_array_sort_with_data (GByteArray *array,
|
|
GCompareDataFunc compare_func,
|
|
gpointer user_data);
|
|
|
|
G_END_DECLS
|
|
|
|
#endif /* __G_ARRAY_H__ */
|