File: | ctk/ctkallocatedbitmask.c |
Warning: | line 278, column 31 The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright © 2011 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.1 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 Public | |||
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
16 | * | |||
17 | * Authors: Benjamin Otte <otte@gnome.org> | |||
18 | */ | |||
19 | ||||
20 | #include <config.h> | |||
21 | ||||
22 | #include "ctkallocatedbitmaskprivate.h" | |||
23 | #include "ctkprivate.h" | |||
24 | ||||
25 | ||||
26 | #define VALUE_TYPEgsize gsize | |||
27 | ||||
28 | #define VALUE_SIZE_BITS(sizeof (gsize) * 8) (sizeof (VALUE_TYPEgsize) * 8) | |||
29 | #define VALUE_BIT(idx)(((gsize) 1) << (idx)) (((VALUE_TYPEgsize) 1) << (idx)) | |||
30 | #define ALL_BITS(~((gsize) 0)) (~((VALUE_TYPEgsize) 0)) | |||
31 | ||||
32 | struct _CtkBitmask { | |||
33 | gsize len; | |||
34 | VALUE_TYPEgsize data[1]; | |||
35 | }; | |||
36 | ||||
37 | #define ENSURE_ALLOCATED(mask, heap_mask)do { if (!(!(((gsize) (mask)) & 1))) { heap_mask.data[0] = (((gsize) (mask)) >> ((gsize) 1)); heap_mask.len = heap_mask .data[0] ? 1 : 0; mask = &heap_mask; } } while (0) G_STMT_STARTdo { \ | |||
38 | if (!_ctk_bitmask_is_allocated (mask)(!(((gsize) (mask)) & 1))) \ | |||
39 | { \ | |||
40 | heap_mask.data[0] = _ctk_bitmask_to_bits (mask)(((gsize) (mask)) >> ((gsize) 1)); \ | |||
41 | heap_mask.len = heap_mask.data[0] ? 1 : 0; \ | |||
42 | mask = &heap_mask; \ | |||
43 | } \ | |||
44 | } G_STMT_ENDwhile (0) | |||
45 | ||||
46 | static CtkBitmask * | |||
47 | ctk_allocated_bitmask_resize (CtkBitmask *mask, | |||
48 | gsize size) G_GNUC_WARN_UNUSED_RESULT__attribute__((warn_unused_result)); | |||
49 | static CtkBitmask * | |||
50 | ctk_allocated_bitmask_resize (CtkBitmask *mask, | |||
51 | gsize size) | |||
52 | { | |||
53 | gsize i; | |||
54 | ||||
55 | if (size == mask->len) | |||
56 | return mask; | |||
57 | ||||
58 | mask = g_realloc (mask, sizeof (CtkBitmask) + sizeof(VALUE_TYPEgsize) * (size - 1)); | |||
59 | ||||
60 | for (i = mask->len; i < size; i++) | |||
61 | mask->data[i] = 0; | |||
62 | ||||
63 | mask->len = size; | |||
64 | ||||
65 | return mask; | |||
66 | } | |||
67 | ||||
68 | static CtkBitmask * | |||
69 | ctk_allocated_bitmask_new_for_bits (gsize bits) | |||
70 | { | |||
71 | CtkBitmask *mask; | |||
72 | ||||
73 | mask = g_malloc (sizeof (CtkBitmask)); | |||
74 | mask->len = bits ? 1 : 0; | |||
75 | mask->data[0] = bits; | |||
76 | ||||
77 | return mask; | |||
78 | } | |||
79 | ||||
80 | static CtkBitmask * | |||
81 | ctk_bitmask_ensure_allocated (CtkBitmask *mask) | |||
82 | { | |||
83 | if (_ctk_bitmask_is_allocated (mask)(!(((gsize) (mask)) & 1))) | |||
84 | return mask; | |||
85 | else | |||
86 | return ctk_allocated_bitmask_new_for_bits (_ctk_bitmask_to_bits (mask)(((gsize) (mask)) >> ((gsize) 1))); | |||
87 | } | |||
88 | ||||
89 | CtkBitmask * | |||
90 | _ctk_allocated_bitmask_copy (const CtkBitmask *mask) | |||
91 | { | |||
92 | CtkBitmask *copy; | |||
93 | ||||
94 | ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return (((void*)0)); } } while (0); | |||
95 | ||||
96 | copy = ctk_allocated_bitmask_new_for_bits (0); | |||
97 | ||||
98 | return _ctk_allocated_bitmask_union (copy, mask); | |||
99 | } | |||
100 | ||||
101 | void | |||
102 | _ctk_allocated_bitmask_free (CtkBitmask *mask) | |||
103 | { | |||
104 | ctk_internal_return_if_fail (mask != NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return ; } } while (0); | |||
105 | ||||
106 | g_free (mask); | |||
107 | } | |||
108 | ||||
109 | void | |||
110 | _ctk_allocated_bitmask_print (const CtkBitmask *mask, | |||
111 | GString *string) | |||
112 | { | |||
113 | CtkBitmask mask_allocated; | |||
114 | int i; | |||
115 | ||||
116 | ctk_internal_return_if_fail (mask != NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return ; } } while (0); | |||
117 | ctk_internal_return_if_fail (string != NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "string != ((void*)0)"); return; } } while (0); | |||
118 | ||||
119 | ENSURE_ALLOCATED (mask, mask_allocated)do { if (!(!(((gsize) (mask)) & 1))) { mask_allocated.data [0] = (((gsize) (mask)) >> ((gsize) 1)); mask_allocated .len = mask_allocated.data[0] ? 1 : 0; mask = &mask_allocated ; } } while (0); | |||
120 | ||||
121 | for (i = mask->len * VALUE_SIZE_BITS(sizeof (gsize) * 8) - 1; i >= 0; i--) | |||
122 | { | |||
123 | if (_ctk_allocated_bitmask_get (mask, i)) | |||
124 | break; | |||
125 | } | |||
126 | ||||
127 | if (i < 0) | |||
128 | { | |||
129 | g_string_append_c (string, '0')g_string_append_c_inline (string, '0'); | |||
130 | return; | |||
131 | } | |||
132 | ||||
133 | for (; i >= 0; i--) | |||
134 | { | |||
135 | g_string_append_c (string, _ctk_allocated_bitmask_get (mask, i) ? '1' : '0')g_string_append_c_inline (string, _ctk_allocated_bitmask_get ( mask, i) ? '1' : '0'); | |||
136 | } | |||
137 | } | |||
138 | ||||
139 | /* NB: Call this function whenever the | |||
140 | * array might have become too large. | |||
141 | * _ctk_allocated_bitmask_is_empty() depends on this. | |||
142 | */ | |||
143 | static CtkBitmask * | |||
144 | ctk_allocated_bitmask_shrink (CtkBitmask *mask) G_GNUC_WARN_UNUSED_RESULT__attribute__((warn_unused_result)); | |||
145 | static CtkBitmask * | |||
146 | ctk_allocated_bitmask_shrink (CtkBitmask *mask) | |||
147 | { | |||
148 | guint i; | |||
149 | ||||
150 | for (i = mask->len; i; i--) | |||
151 | { | |||
152 | if (mask->data[i - 1]) | |||
153 | break; | |||
154 | } | |||
155 | ||||
156 | if (i == 0 || | |||
157 | (i == 1 && mask->data[0] < VALUE_BIT (CTK_BITMASK_N_DIRECT_BITS)(((gsize) 1) << ((sizeof (gsize) * 8 - 1))))) | |||
158 | { | |||
159 | CtkBitmask *result = _ctk_bitmask_from_bits (i == 0 ? 0 : mask->data[0])((gpointer) (guintptr) (gsize) ((((gsize) (i == 0 ? 0 : mask-> data[0])) << 1) | 1)); | |||
160 | _ctk_allocated_bitmask_free (mask); | |||
161 | return result; | |||
162 | } | |||
163 | ||||
164 | return ctk_allocated_bitmask_resize (mask, i); | |||
165 | } | |||
166 | ||||
167 | CtkBitmask * | |||
168 | _ctk_allocated_bitmask_intersect (CtkBitmask *mask, | |||
169 | const CtkBitmask *other) | |||
170 | { | |||
171 | CtkBitmask other_allocated; | |||
172 | guint i; | |||
173 | ||||
174 | ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return (((void*)0)); } } while (0); | |||
175 | ctk_internal_return_val_if_fail (other != NULL, NULL)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return (((void*)0)); } } while (0); | |||
176 | ||||
177 | mask = ctk_bitmask_ensure_allocated (mask); | |||
178 | ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data [0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated .len = other_allocated.data[0] ? 1 : 0; other = &other_allocated ; } } while (0); | |||
179 | ||||
180 | for (i = 0; i < MIN (mask->len, other->len)(((mask->len) < (other->len)) ? (mask->len) : (other ->len)); i++) | |||
181 | { | |||
182 | mask->data[i] &= other->data[i]; | |||
183 | } | |||
184 | for (; i < mask->len; i++) | |||
185 | { | |||
186 | mask->data[i] = 0; | |||
187 | } | |||
188 | ||||
189 | return ctk_allocated_bitmask_shrink (mask); | |||
190 | } | |||
191 | ||||
192 | CtkBitmask * | |||
193 | _ctk_allocated_bitmask_union (CtkBitmask *mask, | |||
194 | const CtkBitmask *other) | |||
195 | { | |||
196 | CtkBitmask other_allocated; | |||
197 | guint i; | |||
198 | ||||
199 | ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return (((void*)0)); } } while (0); | |||
200 | ctk_internal_return_val_if_fail (other != NULL, NULL)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return (((void*)0)); } } while (0); | |||
201 | ||||
202 | mask = ctk_bitmask_ensure_allocated (mask); | |||
203 | ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data [0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated .len = other_allocated.data[0] ? 1 : 0; other = &other_allocated ; } } while (0); | |||
204 | ||||
205 | mask = ctk_allocated_bitmask_resize (mask, MAX (mask->len, other->len)(((mask->len) > (other->len)) ? (mask->len) : (other ->len))); | |||
206 | for (i = 0; i < other->len; i++) | |||
207 | { | |||
208 | mask->data[i] |= other->data[i]; | |||
209 | } | |||
210 | ||||
211 | return mask; | |||
212 | } | |||
213 | ||||
214 | CtkBitmask * | |||
215 | _ctk_allocated_bitmask_subtract (CtkBitmask *mask, | |||
216 | const CtkBitmask *other) | |||
217 | { | |||
218 | CtkBitmask other_allocated; | |||
219 | guint i, len; | |||
220 | ||||
221 | ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return (((void*)0)); } } while (0); | |||
222 | ctk_internal_return_val_if_fail (other != NULL, NULL)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return (((void*)0)); } } while (0); | |||
223 | ||||
224 | mask = ctk_bitmask_ensure_allocated (mask); | |||
225 | ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data [0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated .len = other_allocated.data[0] ? 1 : 0; other = &other_allocated ; } } while (0); | |||
226 | ||||
227 | len = MIN (mask->len, other->len)(((mask->len) < (other->len)) ? (mask->len) : (other ->len)); | |||
228 | for (i = 0; i < len; i++) | |||
229 | { | |||
230 | mask->data[i] &= ~other->data[i]; | |||
231 | } | |||
232 | ||||
233 | return ctk_allocated_bitmask_shrink (mask); | |||
234 | } | |||
235 | ||||
236 | static inline void | |||
237 | ctk_allocated_bitmask_indexes (guint index_, | |||
238 | guint *array_index, | |||
239 | guint *bit_index) | |||
240 | { | |||
241 | *array_index = index_ / VALUE_SIZE_BITS(sizeof (gsize) * 8); | |||
242 | *bit_index = index_ % VALUE_SIZE_BITS(sizeof (gsize) * 8); | |||
243 | } | |||
244 | ||||
245 | gboolean | |||
246 | _ctk_allocated_bitmask_get (const CtkBitmask *mask, | |||
247 | guint index_) | |||
248 | { | |||
249 | guint array_index, bit_index; | |||
250 | ||||
251 | ctk_internal_return_val_if_fail (mask != NULL, FALSE)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return ((0)); } } while (0); | |||
252 | ||||
253 | ctk_allocated_bitmask_indexes (index_, &array_index, &bit_index); | |||
254 | ||||
255 | if (array_index >= mask->len) | |||
256 | return FALSE(0); | |||
257 | ||||
258 | return (mask->data[array_index] & VALUE_BIT (bit_index)(((gsize) 1) << (bit_index))) ? TRUE(!(0)) : FALSE(0); | |||
259 | } | |||
260 | ||||
261 | CtkBitmask * | |||
262 | _ctk_allocated_bitmask_set (CtkBitmask *mask, | |||
263 | guint index_, | |||
264 | gboolean value) | |||
265 | { | |||
266 | guint array_index, bit_index; | |||
267 | ||||
268 | ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return (((void*)0)); } } while (0); | |||
| ||||
269 | ||||
270 | mask = ctk_bitmask_ensure_allocated (mask); | |||
271 | ctk_allocated_bitmask_indexes (index_, &array_index, &bit_index); | |||
272 | ||||
273 | if (value) | |||
274 | { | |||
275 | if (array_index >= mask->len) | |||
276 | mask = ctk_allocated_bitmask_resize (mask, array_index + 1); | |||
277 | ||||
278 | mask->data[array_index] |= VALUE_BIT (bit_index)(((gsize) 1) << (bit_index)); | |||
| ||||
279 | } | |||
280 | else | |||
281 | { | |||
282 | if (array_index < mask->len) | |||
283 | { | |||
284 | mask->data[array_index] &= ~ VALUE_BIT (bit_index)(((gsize) 1) << (bit_index)); | |||
285 | mask = ctk_allocated_bitmask_shrink (mask); | |||
286 | } | |||
287 | } | |||
288 | ||||
289 | return mask; | |||
290 | } | |||
291 | ||||
292 | CtkBitmask * | |||
293 | _ctk_allocated_bitmask_invert_range (CtkBitmask *mask, | |||
294 | guint start, | |||
295 | guint end) | |||
296 | { | |||
297 | guint i; | |||
298 | guint start_word, start_bit; | |||
299 | guint end_word, end_bit; | |||
300 | ||||
301 | ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return (((void*)0)); } } while (0); | |||
302 | ctk_internal_return_val_if_fail (start < end, NULL)do { if ((start < end)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "start < end"); return (((void*)0)); } } while (0); | |||
303 | ||||
304 | mask = ctk_bitmask_ensure_allocated (mask); | |||
305 | ||||
306 | ctk_allocated_bitmask_indexes (start, &start_word, &start_bit); | |||
307 | ctk_allocated_bitmask_indexes (end - 1, &end_word, &end_bit); | |||
308 | ||||
309 | if (end_word >= mask->len) | |||
310 | mask = ctk_allocated_bitmask_resize (mask, end_word + 1); | |||
311 | ||||
312 | for (i = start_word; i <= end_word; i++) | |||
313 | mask->data[i] ^= ALL_BITS(~((gsize) 0)); | |||
314 | mask->data[start_word] ^= (((VALUE_TYPEgsize) 1) << start_bit) - 1; | |||
315 | if (end_bit != VALUE_SIZE_BITS(sizeof (gsize) * 8) - 1) | |||
316 | mask->data[end_word] ^= ALL_BITS(~((gsize) 0)) << (end_bit + 1); | |||
317 | ||||
318 | return ctk_allocated_bitmask_shrink (mask); | |||
319 | } | |||
320 | ||||
321 | gboolean | |||
322 | _ctk_allocated_bitmask_equals (const CtkBitmask *mask, | |||
323 | const CtkBitmask *other) | |||
324 | { | |||
325 | guint i; | |||
326 | ||||
327 | ctk_internal_return_val_if_fail (mask != NULL, FALSE)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return ((0)); } } while (0); | |||
328 | ctk_internal_return_val_if_fail (other != NULL, FALSE)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return ((0)); } } while (0); | |||
329 | ||||
330 | if (mask->len != other->len) | |||
331 | return FALSE(0); | |||
332 | ||||
333 | for (i = 0; i < mask->len; i++) | |||
334 | { | |||
335 | if (mask->data[i] != other->data[i]) | |||
336 | return FALSE(0); | |||
337 | } | |||
338 | ||||
339 | return TRUE(!(0)); | |||
340 | } | |||
341 | ||||
342 | gboolean | |||
343 | _ctk_allocated_bitmask_intersects (const CtkBitmask *mask, | |||
344 | const CtkBitmask *other) | |||
345 | { | |||
346 | CtkBitmask mask_allocated, other_allocated; | |||
347 | int i; | |||
348 | ||||
349 | ctk_internal_return_val_if_fail (mask != NULL, FALSE)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return ((0)); } } while (0); | |||
350 | ctk_internal_return_val_if_fail (other != NULL, FALSE)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return ((0)); } } while (0); | |||
351 | ||||
352 | ENSURE_ALLOCATED (mask, mask_allocated)do { if (!(!(((gsize) (mask)) & 1))) { mask_allocated.data [0] = (((gsize) (mask)) >> ((gsize) 1)); mask_allocated .len = mask_allocated.data[0] ? 1 : 0; mask = &mask_allocated ; } } while (0); | |||
353 | ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data [0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated .len = other_allocated.data[0] ? 1 : 0; other = &other_allocated ; } } while (0); | |||
354 | ||||
355 | for (i = MIN (mask->len, other->len)(((mask->len) < (other->len)) ? (mask->len) : (other ->len)) - 1; i >= 0; i--) | |||
356 | { | |||
357 | if (mask->data[i] & other->data[i]) | |||
358 | return TRUE(!(0)); | |||
359 | } | |||
360 | ||||
361 | return FALSE(0); | |||
362 | } | |||
363 |