Add g_type_default_interface_ref/peek/unref for accessing the default
[platform/upstream/glib.git] / gobject / gvaluearray.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 2001 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * MT safe
22  */
23
24 #include <config.h>
25
26 #include        "gvaluearray.h"
27 #include        <string.h>
28 #include        <stdlib.h>      /* qsort() */
29
30 #ifdef  DISABLE_MEM_POOLS
31 #  define       GROUP_N_VALUES  (1)     /* power of 2 !! */
32 #else
33 #  define       GROUP_N_VALUES  (8)     /* power of 2 !! */
34 #endif
35
36
37 /* --- functions --- */
38 GValue*
39 g_value_array_get_nth (GValueArray *value_array,
40                        guint        index)
41 {
42   g_return_val_if_fail (value_array != NULL, NULL);
43   g_return_val_if_fail (index < value_array->n_values, NULL);
44
45   return value_array->values + index;
46 }
47
48 static inline void
49 value_array_grow (GValueArray *value_array,
50                   guint        n_values,
51                   gboolean     zero_init)
52 {
53   g_return_if_fail (n_values >= value_array->n_values);
54
55   value_array->n_values = n_values;
56   if (value_array->n_values > value_array->n_prealloced)
57     {
58       guint i = value_array->n_prealloced;
59
60       value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
61       value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
62       if (!zero_init)
63         i = value_array->n_values;
64       memset (value_array->values + i, 0,
65               (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
66     }
67 }
68
69 static inline void
70 value_array_shrink (GValueArray *value_array)
71 {
72 #ifdef  DISABLE_MEM_POOLS
73   if (value_array->n_prealloced >= value_array->n_values + GROUP_N_VALUES)
74     {
75       value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
76       value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
77     }
78 #endif
79 }
80
81 GValueArray*
82 g_value_array_new (guint n_prealloced)
83 {
84   GValueArray *value_array = g_new (GValueArray, 1);
85
86   value_array->n_values = 0;
87   value_array->n_prealloced = 0;
88   value_array->values = NULL;
89   value_array_grow (value_array, n_prealloced, TRUE);
90   value_array->n_values = 0;
91
92   return value_array;
93 }
94
95 void
96 g_value_array_free (GValueArray *value_array)
97 {
98   guint i;
99
100   g_return_if_fail (value_array != NULL);
101
102   for (i = 0; i < value_array->n_values; i++)
103     {
104       GValue *value = value_array->values + i;
105
106       if (G_VALUE_TYPE (value) != 0) /* we allow unset values in the array */
107         g_value_unset (value);
108     }
109   g_free (value_array->values);
110   g_free (value_array);
111 }
112
113 GValueArray*
114 g_value_array_copy (const GValueArray *value_array)
115 {
116   GValueArray *new_array;
117   guint i;
118
119   g_return_val_if_fail (value_array != NULL, NULL);
120
121   new_array = g_new (GValueArray, 1);
122   new_array->n_values = 0;
123   new_array->values = NULL;
124   new_array->n_prealloced = 0;
125   value_array_grow (new_array, value_array->n_values, TRUE);
126   for (i = 0; i < new_array->n_values; i++)
127     if (G_VALUE_TYPE (value_array->values + i) != 0)
128       {
129         GValue *value = new_array->values + i;
130         
131         g_value_init (value, G_VALUE_TYPE (value_array->values + i));
132         g_value_copy (value_array->values + i, value);
133       }
134   return new_array;
135 }
136
137 GValueArray*
138 g_value_array_prepend (GValueArray  *value_array,
139                        const GValue *value)
140 {
141   g_return_val_if_fail (value_array != NULL, NULL);
142
143   return g_value_array_insert (value_array, 0, value);
144 }
145
146 GValueArray*
147 g_value_array_append (GValueArray  *value_array,
148                       const GValue *value)
149 {
150   g_return_val_if_fail (value_array != NULL, NULL);
151
152   return g_value_array_insert (value_array, value_array->n_values, value);
153 }
154
155 GValueArray*
156 g_value_array_insert (GValueArray  *value_array,
157                       guint         index,
158                       const GValue *value)
159 {
160   guint i;
161
162   g_return_val_if_fail (value_array != NULL, NULL);
163   g_return_val_if_fail (index <= value_array->n_values, value_array);
164
165   /* we support NULL for "value" as a shortcut for an unset value */
166
167   i = value_array->n_values;
168   value_array_grow (value_array, value_array->n_values + 1, FALSE);
169   if (index + 1 < value_array->n_values)
170     g_memmove (value_array->values + index + 1, value_array->values + index,
171                (i - index) * sizeof (value_array->values[0]));
172   memset (value_array->values + index, 0, sizeof (value_array->values[0]));
173   if (value)
174     {
175       g_value_init (value_array->values + index, G_VALUE_TYPE (value));
176       g_value_copy (value, value_array->values + index);
177     }
178   return value_array;
179 }
180
181 GValueArray*
182 g_value_array_remove (GValueArray *value_array,
183                       guint        index)
184 {
185   g_return_val_if_fail (value_array != NULL, NULL);
186   g_return_val_if_fail (index < value_array->n_values, value_array);
187
188   if (G_VALUE_TYPE (value_array->values + index) != 0)
189     g_value_unset (value_array->values + index);
190   value_array->n_values--;
191   if (index < value_array->n_values)
192     g_memmove (value_array->values + index, value_array->values + index + 1,
193                (value_array->n_values - index) * sizeof (value_array->values[0]));
194   value_array_shrink (value_array);
195   if (value_array->n_prealloced > value_array->n_values)
196     memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
197
198   return value_array;
199 }
200
201 GValueArray*
202 g_value_array_sort (GValueArray *value_array,
203                     GCompareFunc compare_func)
204 {
205   g_return_val_if_fail (compare_func != NULL, NULL);
206
207   if (value_array->n_values)
208     qsort (value_array->values,
209            value_array->n_values,
210            sizeof (value_array->values[0]),
211            compare_func);
212   return value_array;
213 }
214
215 GValueArray*
216 g_value_array_sort_with_data (GValueArray     *value_array,
217                               GCompareDataFunc compare_func,
218                               gpointer         user_data)
219 {
220   g_return_val_if_fail (value_array != NULL, NULL);
221   g_return_val_if_fail (compare_func != NULL, NULL);
222
223   if (value_array->n_values)
224     g_qsort_with_data (value_array->values,
225                        value_array->n_values,
226                        sizeof (value_array->values[0]),
227                        compare_func, user_data);
228   return value_array;
229 }