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