mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 06:56:14 +01:00
Bug 580450 – Reference counting and boxed types for arrays
Add reference counting and boxed types for GArray, GByteArray and GPtrArray. Signed-off-by: Matthias Clasen <mclasen@redhat.com>
This commit is contained in:
parent
d80e12104f
commit
402847c887
@ -2117,6 +2117,9 @@ g_string_chunk_free
|
||||
GArray
|
||||
g_array_new
|
||||
g_array_sized_new
|
||||
g_array_ref
|
||||
g_array_unref
|
||||
g_array_get_element_size
|
||||
g_array_append_val
|
||||
g_array_append_vals
|
||||
g_array_prepend_val
|
||||
@ -2139,6 +2142,10 @@ g_array_free
|
||||
GPtrArray
|
||||
g_ptr_array_new
|
||||
g_ptr_array_sized_new
|
||||
g_ptr_array_new_with_free_func
|
||||
g_ptr_array_set_free_func
|
||||
g_ptr_array_ref
|
||||
g_ptr_array_unref
|
||||
g_ptr_array_add
|
||||
g_ptr_array_remove
|
||||
g_ptr_array_remove_index
|
||||
@ -2160,6 +2167,8 @@ g_ptr_array_foreach
|
||||
GByteArray
|
||||
g_byte_array_new
|
||||
g_byte_array_sized_new
|
||||
g_byte_array_ref
|
||||
g_byte_array_unref
|
||||
g_byte_array_append
|
||||
g_byte_array_prepend
|
||||
g_byte_array_remove_index
|
||||
|
@ -69,7 +69,7 @@ added to the #GArray.
|
||||
|
||||
<!-- ##### FUNCTION g_array_new ##### -->
|
||||
<para>
|
||||
Creates a new #GArray.
|
||||
Creates a new #GArray with a reference count of 1.
|
||||
</para>
|
||||
|
||||
@zero_terminated: %TRUE if the array should have an extra element at the end
|
||||
@ -83,9 +83,9 @@ when they are allocated.
|
||||
<!-- ##### FUNCTION g_array_sized_new ##### -->
|
||||
<para>
|
||||
Creates a new #GArray with @reserved_size elements
|
||||
preallocated. This avoids frequent reallocation, if you are going to
|
||||
add many elements to the array. Note however that the size of the
|
||||
array is still 0.
|
||||
preallocated and a reference count of 1. This avoids frequent reallocation,
|
||||
if you are going to add many elements to the array. Note however that the
|
||||
size of the array is still 0.
|
||||
</para>
|
||||
|
||||
@zero_terminated: %TRUE if the array should have an extra element at the end with all bits cleared.
|
||||
@ -95,6 +95,32 @@ array is still 0.
|
||||
@Returns: the new #GArray.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_array_ref ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_array_unref ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_array_get_element_size ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### MACRO g_array_append_val ##### -->
|
||||
<para>
|
||||
Adds the value on to the end of the array.
|
||||
@ -292,8 +318,11 @@ If the array was created with @clear_ set to %TRUE, the new elements are set to
|
||||
<para>
|
||||
Frees the memory allocated for the #GArray.
|
||||
If @free_segment is %TRUE it frees the memory block holding the elements
|
||||
as well. Pass %FALSE if you want to free the #GArray wrapper but preserve
|
||||
the underlying array for use elsewhere.
|
||||
as well and also each element if @array has a @element_free_func set.
|
||||
Pass %FALSE if you want to free the #GArray wrapper but preserve
|
||||
the underlying array for use elsewhere. If the reference count of @array
|
||||
is greater than one, the #GArray wrapper is preserved but the size of
|
||||
@array will be set to zero.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
|
@ -63,7 +63,7 @@ added to the #GByteArray.
|
||||
|
||||
<!-- ##### FUNCTION g_byte_array_new ##### -->
|
||||
<para>
|
||||
Creates a new #GByteArray.
|
||||
Creates a new #GByteArray with a reference count of 1.
|
||||
</para>
|
||||
|
||||
@Returns: the new #GByteArray.
|
||||
@ -80,6 +80,23 @@ the array. Note however that the size of the array is still 0.
|
||||
@Returns: the new #GByteArray.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_byte_array_ref ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_byte_array_unref ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_byte_array_append ##### -->
|
||||
<para>
|
||||
Adds the given bytes to the end of the #GByteArray.
|
||||
@ -181,7 +198,9 @@ Sets the size of the #GByteArray, expanding it if necessary.
|
||||
<!-- ##### FUNCTION g_byte_array_free ##### -->
|
||||
<para>
|
||||
Frees the memory allocated by the #GByteArray.
|
||||
If @free_segment is %TRUE it frees the actual byte data.
|
||||
If @free_segment is %TRUE it frees the actual byte data. If the reference
|
||||
count of @array is greater than one, the #GByteArray wrapper is preserved but
|
||||
the size of @array will be set to zero.
|
||||
</para>
|
||||
|
||||
@array: a #GByteArray.
|
||||
|
@ -73,7 +73,7 @@ Contains the public fields of a pointer array.
|
||||
|
||||
<!-- ##### FUNCTION g_ptr_array_new ##### -->
|
||||
<para>
|
||||
Creates a new #GPtrArray.
|
||||
Creates a new #GPtrArray with a reference count of 1.
|
||||
</para>
|
||||
|
||||
@Returns: the new #GPtrArray.
|
||||
@ -82,15 +82,50 @@ Creates a new #GPtrArray.
|
||||
<!-- ##### FUNCTION g_ptr_array_sized_new ##### -->
|
||||
<para>
|
||||
Creates a new #GPtrArray with @reserved_size pointers
|
||||
preallocated. This avoids frequent reallocation, if you are going to
|
||||
add many pointers to the array. Note however that the size of the
|
||||
array is still 0.
|
||||
preallocated and a reference count of 1. This avoids frequent reallocation,
|
||||
if you are going to add many pointers to the array. Note however that the size
|
||||
of the array is still 0.
|
||||
</para>
|
||||
|
||||
@reserved_size: number of pointers preallocated.
|
||||
@Returns: the new #GPtrArray.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ptr_array_new_with_free_func ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@element_free_func:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ptr_array_set_free_func ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
@element_free_func:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ptr_array_ref ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ptr_array_unref ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@array:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ptr_array_add ##### -->
|
||||
<para>
|
||||
Adds a pointer to the end of the pointer array.
|
||||
@ -105,6 +140,8 @@ The array will grow in size automatically if necessary.
|
||||
<para>
|
||||
Removes the first occurrence of the given pointer from the pointer array.
|
||||
The following elements are moved down one place.
|
||||
If @array has a non-%NULL #GDestroyNotify function it is called for
|
||||
the removed element.
|
||||
</para>
|
||||
<para>
|
||||
It returns %TRUE if the pointer was removed, or %FALSE if the pointer
|
||||
@ -121,6 +158,8 @@ in the array.
|
||||
<para>
|
||||
Removes the pointer at the given index from the pointer array.
|
||||
The following elements are moved down one place.
|
||||
If @array has a non-%NULL #GDestroyNotify function it is called for
|
||||
the removed element.
|
||||
</para>
|
||||
|
||||
@array: a #GPtrArray.
|
||||
@ -134,6 +173,8 @@ Removes the first occurrence of the given pointer from the pointer array.
|
||||
The last element in the array is used to fill in the space, so this function
|
||||
does not preserve the order of the array. But it is faster than
|
||||
g_ptr_array_remove().
|
||||
If @array has a non-%NULL #GDestroyNotify function it is called for
|
||||
the removed element.
|
||||
</para>
|
||||
<para>
|
||||
It returns %TRUE if the pointer was removed, or %FALSE if the pointer
|
||||
@ -151,6 +192,8 @@ Removes the pointer at the given index from the pointer array.
|
||||
The last element in the array is used to fill in the space, so this function
|
||||
does not preserve the order of the array. But it is faster than
|
||||
g_ptr_array_remove_index().
|
||||
If @array has a non-%NULL #GDestroyNotify function it is called for
|
||||
the removed element.
|
||||
</para>
|
||||
|
||||
@array: a #GPtrArray.
|
||||
@ -162,6 +205,8 @@ g_ptr_array_remove_index().
|
||||
<para>
|
||||
Removes the given number of pointers starting at the given index from a
|
||||
#GPtrArray. The following elements are moved to close the gap.
|
||||
If @array has a non-%NULL #GDestroyNotify function it is called for
|
||||
the removed elements.
|
||||
</para>
|
||||
|
||||
@array: a @GPtrArray.
|
||||
@ -228,14 +273,17 @@ Returns the pointer at the given index of the pointer array.
|
||||
<!-- ##### FUNCTION g_ptr_array_free ##### -->
|
||||
<para>
|
||||
Frees the memory allocated for the #GPtrArray.
|
||||
If @free_segment is %TRUE it frees the memory block holding the elements
|
||||
If @free_seg is %TRUE it frees the memory block holding the elements
|
||||
as well. Pass %FALSE if you want to free the #GPtrArray wrapper but preserve
|
||||
the underlying array for use elsewhere.
|
||||
the underlying array for use elsewhere. If the reference count of @array
|
||||
is greater than one, the #GPtrArray wrapper is preserved but the size of
|
||||
@array will be set to zero.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
If array contents point to dynamically-allocated memory, they should be freed
|
||||
separately.
|
||||
If array contents point to dynamically-allocated memory, they should
|
||||
be freed separately if @free_seg is %TRUE and no #GDestroyNotify
|
||||
function has been set for @array.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
|
233
glib/garray.c
233
glib/garray.c
@ -55,6 +55,7 @@ struct _GRealArray
|
||||
guint elt_size;
|
||||
guint zero_terminated : 1;
|
||||
guint clear : 1;
|
||||
volatile gint ref_count;
|
||||
};
|
||||
|
||||
#define g_array_elt_len(array,i) ((array)->elt_size * (i))
|
||||
@ -91,6 +92,7 @@ GArray* g_array_sized_new (gboolean zero_terminated,
|
||||
array->zero_terminated = (zero_terminated ? 1 : 0);
|
||||
array->clear = (clear ? 1 : 0);
|
||||
array->elt_size = elt_size;
|
||||
array->ref_count = 1;
|
||||
|
||||
if (array->zero_terminated || reserved_size != 0)
|
||||
{
|
||||
@ -101,14 +103,78 @@ GArray* g_array_sized_new (gboolean zero_terminated,
|
||||
return (GArray*) array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_array_ref:
|
||||
* @array: A #GArray.
|
||||
*
|
||||
* Atomically increments the reference count of @array by one. This
|
||||
* function is MT-safe and may be called from any thread.
|
||||
*
|
||||
* Returns: The passed in #GArray.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
GArray *
|
||||
g_array_ref (GArray *array)
|
||||
{
|
||||
GRealArray *rarray = (GRealArray*) array;
|
||||
g_return_val_if_fail (g_atomic_int_get (&rarray->ref_count) > 0, array);
|
||||
g_atomic_int_inc (&rarray->ref_count);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_array_unref:
|
||||
* @array: A #GArray.
|
||||
*
|
||||
* Atomically decrements the reference count of @array by one. If the
|
||||
* reference count drops to 0, all memory allocated by the array is
|
||||
* released. This function is MT-safe and may be called from any
|
||||
* thread.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
void
|
||||
g_array_unref (GArray *array)
|
||||
{
|
||||
GRealArray *rarray = (GRealArray*) array;
|
||||
g_return_if_fail (g_atomic_int_get (&rarray->ref_count) > 0);
|
||||
if (g_atomic_int_dec_and_test (&rarray->ref_count))
|
||||
g_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_array_get_element_size:
|
||||
* @array: A #GArray.
|
||||
*
|
||||
* Gets the size of the elements in @array.
|
||||
*
|
||||
* Returns: Size of each element, in bytes.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
guint
|
||||
g_array_get_element_size (GArray *array)
|
||||
{
|
||||
GRealArray *rarray = (GRealArray*) array;
|
||||
return rarray->elt_size;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_array_free (GArray *array,
|
||||
g_array_free (GArray *farray,
|
||||
gboolean free_segment)
|
||||
{
|
||||
GRealArray *array = (GRealArray*) farray;
|
||||
gchar* segment;
|
||||
gboolean preserve_wrapper;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
/* if others are holding a reference, preserve the wrapper but do free/return the data */
|
||||
preserve_wrapper = FALSE;
|
||||
if (g_atomic_int_get (&array->ref_count) > 1)
|
||||
preserve_wrapper = TRUE;
|
||||
|
||||
if (free_segment)
|
||||
{
|
||||
g_free (array->data);
|
||||
@ -117,7 +183,16 @@ g_array_free (GArray *array,
|
||||
else
|
||||
segment = array->data;
|
||||
|
||||
if (preserve_wrapper)
|
||||
{
|
||||
array->data = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_slice_free1 (sizeof (GRealArray), array);
|
||||
}
|
||||
|
||||
return segment;
|
||||
}
|
||||
@ -355,6 +430,8 @@ struct _GRealPtrArray
|
||||
gpointer *pdata;
|
||||
guint len;
|
||||
guint alloc;
|
||||
volatile gint ref_count;
|
||||
GDestroyNotify element_free_func;
|
||||
};
|
||||
|
||||
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
|
||||
@ -374,6 +451,8 @@ g_ptr_array_sized_new (guint reserved_size)
|
||||
array->pdata = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
array->ref_count = 1;
|
||||
array->element_free_func = NULL;
|
||||
|
||||
if (reserved_size != 0)
|
||||
g_ptr_array_maybe_expand (array, reserved_size);
|
||||
@ -381,23 +460,123 @@ g_ptr_array_sized_new (guint reserved_size)
|
||||
return (GPtrArray*) array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_new_with_free_func:
|
||||
* @element_free_func: A function to free elements with destroy @array or %NULL.
|
||||
*
|
||||
* Creates a new #GPtrArray with a reference count of 1 and use @element_free_func
|
||||
* for freeing each element when the array is destroyed either via
|
||||
* g_ptr_array_unref(), when g_ptr_array_free() is called with @free_segment
|
||||
* set to %TRUE or when removing elements.
|
||||
*
|
||||
* Returns: A new #GPtrArray.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
GPtrArray *
|
||||
g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
|
||||
{
|
||||
GPtrArray *array;
|
||||
|
||||
array = g_ptr_array_new ();
|
||||
g_ptr_array_set_free_func (array, element_free_func);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_set_free_func:
|
||||
* @array: A #GPtrArray.
|
||||
* @element_free_func: A function to free elements with destroy @array or %NULL.
|
||||
*
|
||||
* Sets a function for freeing each element when @array is destroyed
|
||||
* either via g_ptr_array_unref(), when g_ptr_array_free() is called
|
||||
* with @free_segment set to %TRUE or when removing elements.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
void
|
||||
g_ptr_array_set_free_func (GPtrArray *array,
|
||||
GDestroyNotify element_free_func)
|
||||
{
|
||||
GRealPtrArray* rarray = (GRealPtrArray*) array;
|
||||
rarray->element_free_func = element_free_func;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_ref:
|
||||
* @array: A #GArray.
|
||||
*
|
||||
* Atomically increments the reference count of @array by one. This
|
||||
* function is MT-safe and may be called from any thread.
|
||||
*
|
||||
* Returns: The passed in #GPtrArray.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
GPtrArray *
|
||||
g_ptr_array_ref (GPtrArray *array)
|
||||
{
|
||||
GRealPtrArray *rarray = (GRealPtrArray*) array;
|
||||
g_return_val_if_fail (g_atomic_int_get (&rarray->ref_count) > 0, array);
|
||||
g_atomic_int_inc (&rarray->ref_count);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_unref:
|
||||
* @array: A #GPtrArray.
|
||||
*
|
||||
* Atomically decrements the reference count of @array by one. If the
|
||||
* reference count drops to 0, the effect is the same as calling
|
||||
* g_ptr_array_free() with @free_segment set to %TRUE. This function
|
||||
* is MT-safe and may be called from any thread.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
void
|
||||
g_ptr_array_unref (GPtrArray *array)
|
||||
{
|
||||
GRealPtrArray *rarray = (GRealPtrArray*) array;
|
||||
g_return_if_fail (g_atomic_int_get (&rarray->ref_count) > 0);
|
||||
if (g_atomic_int_dec_and_test (&rarray->ref_count))
|
||||
g_ptr_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
gpointer*
|
||||
g_ptr_array_free (GPtrArray *array,
|
||||
g_ptr_array_free (GPtrArray *farray,
|
||||
gboolean free_segment)
|
||||
{
|
||||
GRealPtrArray *array = (GRealPtrArray*) farray;
|
||||
gpointer* segment;
|
||||
gboolean preserve_wrapper;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
/* if others are holding a reference, preserve the wrapper but do free/return the data */
|
||||
preserve_wrapper = FALSE;
|
||||
if (g_atomic_int_get (&array->ref_count) > 1)
|
||||
preserve_wrapper = TRUE;
|
||||
|
||||
if (free_segment)
|
||||
{
|
||||
if (array->element_free_func != NULL)
|
||||
g_ptr_array_foreach (farray, (GFunc) array->element_free_func, NULL);
|
||||
g_free (array->pdata);
|
||||
segment = NULL;
|
||||
}
|
||||
else
|
||||
segment = array->pdata;
|
||||
|
||||
if (preserve_wrapper)
|
||||
{
|
||||
array->pdata = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_slice_free1 (sizeof (GRealPtrArray), array);
|
||||
}
|
||||
|
||||
return segment;
|
||||
}
|
||||
@ -462,6 +641,9 @@ g_ptr_array_remove_index (GPtrArray *farray,
|
||||
|
||||
result = array->pdata[index_];
|
||||
|
||||
if (array->element_free_func != NULL)
|
||||
array->element_free_func (array->pdata[index_]);
|
||||
|
||||
if (index_ != array->len - 1)
|
||||
g_memmove (array->pdata + index_, array->pdata + index_ + 1,
|
||||
sizeof (gpointer) * (array->len - index_ - 1));
|
||||
@ -488,7 +670,11 @@ g_ptr_array_remove_index_fast (GPtrArray *farray,
|
||||
result = array->pdata[index_];
|
||||
|
||||
if (index_ != array->len - 1)
|
||||
{
|
||||
if (array->element_free_func != NULL)
|
||||
array->element_free_func (array->pdata[index_]);
|
||||
array->pdata[index_] = array->pdata[array->len - 1];
|
||||
}
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
@ -504,15 +690,24 @@ g_ptr_array_remove_range (GPtrArray *farray,
|
||||
guint length)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
guint n;
|
||||
|
||||
g_return_if_fail (array);
|
||||
g_return_if_fail (index_ < array->len);
|
||||
g_return_if_fail (index_ + length <= array->len);
|
||||
|
||||
if (array->element_free_func != NULL)
|
||||
{
|
||||
for (n = index_; n < index_ + length; n++)
|
||||
array->element_free_func (array->pdata[n]);
|
||||
}
|
||||
|
||||
if (index_ + length != array->len)
|
||||
{
|
||||
g_memmove (&array->pdata[index_],
|
||||
&array->pdata[index_ + length],
|
||||
(array->len - (index_ + length)) * sizeof (gpointer));
|
||||
}
|
||||
|
||||
array->len -= length;
|
||||
if (G_UNLIKELY (g_mem_gc_friendly))
|
||||
@ -646,6 +841,40 @@ guint8* g_byte_array_free (GByteArray *array,
|
||||
return (guint8*) g_array_free ((GArray*) array, free_segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_byte_array_ref:
|
||||
* @array: A #GByteArray.
|
||||
*
|
||||
* Atomically increments the reference count of @array by one. This
|
||||
* function is MT-safe and may be called from any thread.
|
||||
*
|
||||
* Returns: The passed in #GByteArray.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
GByteArray *
|
||||
g_byte_array_ref (GByteArray *array)
|
||||
{
|
||||
return (GByteArray *) g_array_ref ((GArray *) array);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_byte_array_unref:
|
||||
* @array: A #GByteArray.
|
||||
*
|
||||
* Atomically decrements the reference count of @array by one. If the
|
||||
* reference count drops to 0, all memory allocated by the array is
|
||||
* released. This function is MT-safe and may be called from any
|
||||
* thread.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
void
|
||||
g_byte_array_unref (GByteArray *array)
|
||||
{
|
||||
g_array_unref ((GArray *) array);
|
||||
}
|
||||
|
||||
GByteArray* g_byte_array_append (GByteArray *array,
|
||||
const guint8 *data,
|
||||
guint len)
|
||||
|
@ -76,6 +76,9 @@ GArray* g_array_sized_new (gboolean zero_terminated,
|
||||
guint reserved_size);
|
||||
gchar* g_array_free (GArray *array,
|
||||
gboolean free_segment);
|
||||
GArray *g_array_ref (GArray *array);
|
||||
void g_array_unref (GArray *array);
|
||||
guint g_array_get_element_size (GArray *array);
|
||||
GArray* g_array_append_vals (GArray *array,
|
||||
gconstpointer data,
|
||||
guint len);
|
||||
@ -107,9 +110,14 @@ void g_array_sort_with_data (GArray *array,
|
||||
*/
|
||||
#define g_ptr_array_index(array,index_) ((array)->pdata)[index_]
|
||||
GPtrArray* g_ptr_array_new (void);
|
||||
GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func);
|
||||
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
||||
gpointer* g_ptr_array_free (GPtrArray *array,
|
||||
gboolean free_seg);
|
||||
GPtrArray* g_ptr_array_ref (GPtrArray *array);
|
||||
void g_ptr_array_unref (GPtrArray *array);
|
||||
void g_ptr_array_set_free_func (GPtrArray *array,
|
||||
GDestroyNotify element_free_func);
|
||||
void g_ptr_array_set_size (GPtrArray *array,
|
||||
gint length);
|
||||
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
||||
@ -143,6 +151,8 @@ GByteArray* g_byte_array_new (void);
|
||||
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
||||
guint8* g_byte_array_free (GByteArray *array,
|
||||
gboolean free_segment);
|
||||
GByteArray *g_byte_array_ref (GByteArray *array);
|
||||
void g_byte_array_unref (GByteArray *array);
|
||||
GByteArray* g_byte_array_append (GByteArray *array,
|
||||
const guint8 *data,
|
||||
guint len);
|
||||
|
@ -17,6 +17,9 @@ g_array_append_vals
|
||||
g_array_free
|
||||
g_array_insert_vals
|
||||
g_array_new
|
||||
g_array_ref
|
||||
g_array_unref
|
||||
g_array_get_element_size
|
||||
g_array_prepend_vals
|
||||
g_array_remove_index
|
||||
g_array_remove_index_fast
|
||||
@ -27,6 +30,8 @@ g_array_sort
|
||||
g_array_sort_with_data
|
||||
g_byte_array_append
|
||||
g_byte_array_free
|
||||
g_byte_array_unref
|
||||
g_byte_array_ref
|
||||
g_byte_array_new
|
||||
g_byte_array_prepend
|
||||
g_byte_array_remove_index
|
||||
@ -39,7 +44,11 @@ g_byte_array_sort_with_data
|
||||
g_ptr_array_add
|
||||
g_ptr_array_foreach
|
||||
g_ptr_array_free
|
||||
g_ptr_array_unref
|
||||
g_ptr_array_ref
|
||||
g_ptr_array_new
|
||||
g_ptr_array_new_with_free_func
|
||||
g_ptr_array_set_free_func
|
||||
g_ptr_array_remove
|
||||
g_ptr_array_remove_fast
|
||||
g_ptr_array_remove_index
|
||||
|
@ -72,6 +72,33 @@ array_prepend (void)
|
||||
g_array_free (garray, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
array_ref_count (void)
|
||||
{
|
||||
GArray *garray;
|
||||
GArray *garray2;
|
||||
gint i;
|
||||
|
||||
garray = g_array_new (FALSE, FALSE, sizeof (gint));
|
||||
g_assert_cmpint (g_array_get_element_size (garray), ==, sizeof (gint));
|
||||
for (i = 0; i < 100; i++)
|
||||
g_array_prepend_val (garray, i);
|
||||
|
||||
/* check we can ref, unref and still access the array */
|
||||
garray2 = g_array_ref (garray);
|
||||
g_assert (garray == garray2);
|
||||
g_array_unref (garray2);
|
||||
for (i = 0; i < 100; i++)
|
||||
g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
|
||||
|
||||
/* garray2 should be an empty valid GArray wrapper */
|
||||
garray2 = g_array_ref (garray);
|
||||
g_array_free (garray, TRUE);
|
||||
|
||||
g_assert_cmpint (garray2->len, ==, 0);
|
||||
g_array_unref (garray2);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_add (void)
|
||||
{
|
||||
@ -92,6 +119,118 @@ pointer_array_add (void)
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_ref_count (void)
|
||||
{
|
||||
GPtrArray *gparray;
|
||||
GPtrArray *gparray2;
|
||||
gint i;
|
||||
gint sum = 0;
|
||||
|
||||
gparray = g_ptr_array_new ();
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_ptr_array_add (gparray, GINT_TO_POINTER (i));
|
||||
|
||||
/* check we can ref, unref and still access the array */
|
||||
gparray2 = g_ptr_array_ref (gparray);
|
||||
g_assert (gparray == gparray2);
|
||||
g_ptr_array_unref (gparray2);
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
|
||||
|
||||
g_ptr_array_foreach (gparray, sum_up, &sum);
|
||||
g_assert (sum == 49995000);
|
||||
|
||||
/* gparray2 should be an empty valid GPtrArray wrapper */
|
||||
gparray2 = g_ptr_array_ref (gparray);
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
|
||||
g_assert_cmpint (gparray2->len, ==, 0);
|
||||
g_ptr_array_unref (gparray2);
|
||||
}
|
||||
|
||||
static gint num_free_func_invocations = 0;
|
||||
|
||||
static void
|
||||
my_free_func (gpointer data)
|
||||
{
|
||||
num_free_func_invocations++;
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_free_func (void)
|
||||
{
|
||||
GPtrArray *gparray;
|
||||
GPtrArray *gparray2;
|
||||
gchar **strv;
|
||||
gchar *s;
|
||||
|
||||
num_free_func_invocations = 0;
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_unref (gparray);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 0);
|
||||
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 0);
|
||||
|
||||
num_free_func_invocations = 0;
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_add (gparray, g_strdup ("foo"));
|
||||
g_ptr_array_add (gparray, g_strdup ("bar"));
|
||||
g_ptr_array_add (gparray, g_strdup ("baz"));
|
||||
g_ptr_array_remove_index (gparray, 0);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 1);
|
||||
s = g_strdup ("frob");
|
||||
g_ptr_array_add (gparray, s);
|
||||
g_assert (g_ptr_array_remove (gparray, s));
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 2);
|
||||
g_ptr_array_ref (gparray);
|
||||
g_ptr_array_unref (gparray);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 2);
|
||||
g_ptr_array_unref (gparray);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 4);
|
||||
|
||||
num_free_func_invocations = 0;
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_add (gparray, g_strdup ("foo"));
|
||||
g_ptr_array_add (gparray, g_strdup ("bar"));
|
||||
g_ptr_array_add (gparray, g_strdup ("baz"));
|
||||
g_ptr_array_add (gparray, NULL);
|
||||
gparray2 = g_ptr_array_ref (gparray);
|
||||
strv = (gchar **) g_ptr_array_free (gparray, FALSE);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 0);
|
||||
g_strfreev (strv);
|
||||
g_ptr_array_unref (gparray2);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 0);
|
||||
|
||||
num_free_func_invocations = 0;
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_add (gparray, g_strdup ("foo"));
|
||||
g_ptr_array_add (gparray, g_strdup ("bar"));
|
||||
g_ptr_array_add (gparray, g_strdup ("baz"));
|
||||
g_ptr_array_unref (gparray);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 3);
|
||||
|
||||
num_free_func_invocations = 0;
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_add (gparray, g_strdup ("foo"));
|
||||
g_ptr_array_add (gparray, g_strdup ("bar"));
|
||||
g_ptr_array_add (gparray, g_strdup ("baz"));
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 3);
|
||||
|
||||
num_free_func_invocations = 0;
|
||||
gparray = g_ptr_array_new_with_free_func (my_free_func);
|
||||
g_ptr_array_add (gparray, "foo");
|
||||
g_ptr_array_add (gparray, "bar");
|
||||
g_ptr_array_add (gparray, "baz");
|
||||
g_ptr_array_set_free_func (gparray, NULL);
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
g_assert_cmpint (num_free_func_invocations, ==, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
byte_array_append (void)
|
||||
{
|
||||
@ -113,6 +252,35 @@ byte_array_append (void)
|
||||
g_byte_array_free (gbarray, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
byte_array_ref_count (void)
|
||||
{
|
||||
GByteArray *gbarray;
|
||||
GByteArray *gbarray2;
|
||||
gint i;
|
||||
|
||||
gbarray = g_byte_array_new ();
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_byte_array_append (gbarray, (guint8*) "abcd", 4);
|
||||
|
||||
gbarray2 = g_byte_array_ref (gbarray);
|
||||
g_assert (gbarray2 == gbarray);
|
||||
g_byte_array_unref (gbarray2);
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
g_assert (gbarray->data[4*i] == 'a');
|
||||
g_assert (gbarray->data[4*i+1] == 'b');
|
||||
g_assert (gbarray->data[4*i+2] == 'c');
|
||||
g_assert (gbarray->data[4*i+3] == 'd');
|
||||
}
|
||||
|
||||
gbarray2 = g_byte_array_ref (gbarray);
|
||||
g_assert (gbarray2 == gbarray);
|
||||
g_byte_array_free (gbarray, TRUE);
|
||||
g_assert_cmpint (gbarray2->len, ==, 0);
|
||||
g_byte_array_unref (gbarray2);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -121,12 +289,16 @@ main (int argc, char *argv[])
|
||||
/* array tests */
|
||||
g_test_add_func ("/array/append", array_append);
|
||||
g_test_add_func ("/array/prepend", array_prepend);
|
||||
g_test_add_func ("/array/ref-count", array_ref_count);
|
||||
|
||||
/* pointer arrays */
|
||||
g_test_add_func ("/pointerarray/add", pointer_array_add);
|
||||
g_test_add_func ("/pointerarray/ref-count", pointer_array_ref_count);
|
||||
g_test_add_func ("/pointerarray/free-func", pointer_array_free_func);
|
||||
|
||||
/* byte arrays */
|
||||
g_test_add_func ("/bytearray/append", byte_array_append);
|
||||
g_test_add_func ("/bytearray/ref-count", byte_array_ref_count);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -274,6 +274,39 @@ g_regex_get_type (void)
|
||||
return type_id;
|
||||
}
|
||||
|
||||
GType
|
||||
g_array_get_type (void)
|
||||
{
|
||||
static GType type_id = 0;
|
||||
if (!type_id)
|
||||
type_id = g_boxed_type_register_static (g_intern_static_string ("GArray"),
|
||||
(GBoxedCopyFunc) g_array_ref,
|
||||
(GBoxedFreeFunc) g_array_unref);
|
||||
return type_id;
|
||||
}
|
||||
|
||||
GType
|
||||
g_ptr_array_get_type (void)
|
||||
{
|
||||
static GType type_id = 0;
|
||||
if (!type_id)
|
||||
type_id = g_boxed_type_register_static (g_intern_static_string ("GPtrArray"),
|
||||
(GBoxedCopyFunc) g_ptr_array_ref,
|
||||
(GBoxedFreeFunc) g_ptr_array_unref);
|
||||
return type_id;
|
||||
}
|
||||
|
||||
GType
|
||||
g_byte_array_get_type (void)
|
||||
{
|
||||
static GType type_id = 0;
|
||||
if (!type_id)
|
||||
type_id = g_boxed_type_register_static (g_intern_static_string ("GByteArray"),
|
||||
(GBoxedCopyFunc) g_byte_array_ref,
|
||||
(GBoxedFreeFunc) g_byte_array_unref);
|
||||
return type_id;
|
||||
}
|
||||
|
||||
static void
|
||||
boxed_proxy_value_init (GValue *value)
|
||||
{
|
||||
|
@ -162,6 +162,30 @@ GType g_boxed_type_register_static (const gchar *name,
|
||||
* Since: 2.14
|
||||
*/
|
||||
#define G_TYPE_REGEX (g_regex_get_type ())
|
||||
/**
|
||||
* G_TYPE_ARRAY:
|
||||
*
|
||||
* The #GType for a boxed type holding a #GArray reference.
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
#define G_TYPE_ARRAY (g_array_get_type ())
|
||||
/**
|
||||
* G_TYPE_BYTE_ARRAY:
|
||||
*
|
||||
* The #GType for a boxed type holding a #GByteArray reference.
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
#define G_TYPE_BYTE_ARRAY (g_byte_array_get_type ())
|
||||
/**
|
||||
* G_TYPE_PTR_ARRAY:
|
||||
*
|
||||
* The #GType for a boxed type holding a #GPtrArray reference.
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
#define G_TYPE_PTR_ARRAY (g_ptr_array_get_type ())
|
||||
|
||||
|
||||
void g_value_take_boxed (GValue *value,
|
||||
@ -177,6 +201,9 @@ GType g_date_get_type (void) G_GNUC_CONST;
|
||||
GType g_strv_get_type (void) G_GNUC_CONST;
|
||||
GType g_gstring_get_type (void) G_GNUC_CONST;
|
||||
GType g_hash_table_get_type (void) G_GNUC_CONST;
|
||||
GType g_array_get_type (void) G_GNUC_CONST;
|
||||
GType g_byte_array_get_type (void) G_GNUC_CONST;
|
||||
GType g_ptr_array_get_type (void) G_GNUC_CONST;
|
||||
GType g_regex_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,9 @@ g_date_get_type G_GNUC_CONST
|
||||
g_gstring_get_type G_GNUC_CONST
|
||||
g_strv_get_type G_GNUC_CONST
|
||||
g_hash_table_get_type G_GNUC_CONST
|
||||
g_array_get_type G_GNUC_CONST
|
||||
g_byte_array_get_type G_GNUC_CONST
|
||||
g_ptr_array_get_type G_GNUC_CONST
|
||||
g_regex_get_type G_GNUC_CONST
|
||||
g_closure_get_type G_GNUC_CONST
|
||||
g_value_get_type G_GNUC_CONST
|
||||
|
Loading…
Reference in New Issue
Block a user