2 * Copyright © 2011 Red Hat Inc.
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.
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.
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/>.
17 * Authors: Benjamin Otte <otte@gnome.org>
22 #include "gtk/gtkallocatedbitmaskprivate.h"
24 #define VALUE_TYPE gsize
26 #define VALUE_SIZE_BITS (sizeof (VALUE_TYPE) * 8)
27 #define VALUE_BIT(idx) (((VALUE_TYPE) 1) << (idx))
34 #define ENSURE_ALLOCATED(mask, heap_mask) G_STMT_START { \
35 if (!_gtk_bitmask_is_allocated (mask)) \
37 heap_mask.data[0] = _gtk_bitmask_to_bits (mask); \
38 heap_mask.len = heap_mask.data[0] ? 1 : 0; \
44 gtk_allocated_bitmask_resize (GtkBitmask *mask,
45 gsize size) G_GNUC_WARN_UNUSED_RESULT;
47 gtk_allocated_bitmask_resize (GtkBitmask *mask,
52 mask = g_realloc (mask, sizeof (GtkBitmask) + sizeof(VALUE_TYPE) * (size - 1));
54 for (i = mask->len; i < size; i++)
63 gtk_allocated_bitmask_new_for_bits (gsize bits)
67 mask = g_malloc (sizeof (GtkBitmask));
68 mask->len = bits ? 1 : 0;
75 gtk_bitmask_ensure_allocated (GtkBitmask *mask)
77 if (_gtk_bitmask_is_allocated (mask))
80 return gtk_allocated_bitmask_new_for_bits (_gtk_bitmask_to_bits (mask));
84 _gtk_allocated_bitmask_copy (const GtkBitmask *mask)
88 g_return_val_if_fail (mask != NULL, NULL);
90 copy = gtk_allocated_bitmask_new_for_bits (0);
92 return _gtk_allocated_bitmask_union (copy, mask);
96 _gtk_allocated_bitmask_free (GtkBitmask *mask)
98 g_return_if_fail (mask != NULL);
104 _gtk_allocated_bitmask_print (const GtkBitmask *mask,
107 GtkBitmask mask_allocated;
110 g_return_if_fail (mask != NULL);
111 g_return_if_fail (string != NULL);
113 ENSURE_ALLOCATED (mask, mask_allocated);
115 for (i = mask->len * VALUE_SIZE_BITS - 1; i >= 0; i--)
117 if (_gtk_allocated_bitmask_get (mask, i))
123 g_string_append_c (string, '0');
129 g_string_append_c (string, _gtk_allocated_bitmask_get (mask, i) ? '1' : '0');
133 /* NB: Call this function whenever the
134 * array might have become too large.
135 * _gtk_allocated_bitmask_is_empty() depends on this.
138 gtk_allocated_bitmask_shrink (GtkBitmask *mask) G_GNUC_WARN_UNUSED_RESULT;
140 gtk_allocated_bitmask_shrink (GtkBitmask *mask)
144 for (i = mask->len; i; i--)
146 if (mask->data[i - 1])
151 (i == 1 && mask->data[0] < VALUE_BIT (GTK_BITMASK_N_DIRECT_BITS)))
153 GtkBitmask *result = _gtk_bitmask_from_bits (i == 0 ? 0 : mask->data[0]);
154 _gtk_allocated_bitmask_free (mask);
158 return gtk_allocated_bitmask_resize (mask, i);
162 _gtk_allocated_bitmask_intersect (GtkBitmask *mask,
163 const GtkBitmask *other)
165 GtkBitmask other_allocated;
168 g_return_val_if_fail (mask != NULL, NULL);
169 g_return_val_if_fail (other != NULL, NULL);
171 mask = gtk_bitmask_ensure_allocated (mask);
172 ENSURE_ALLOCATED (other, other_allocated);
174 mask = gtk_allocated_bitmask_resize (mask, MIN (mask->len, other->len));
175 for (i = 0; i < mask->len; i++)
177 mask->data[i] &= other->data[i];
180 return gtk_allocated_bitmask_shrink (mask);
184 _gtk_allocated_bitmask_union (GtkBitmask *mask,
185 const GtkBitmask *other)
187 GtkBitmask other_allocated;
190 g_return_val_if_fail (mask != NULL, NULL);
191 g_return_val_if_fail (other != NULL, NULL);
193 mask = gtk_bitmask_ensure_allocated (mask);
194 ENSURE_ALLOCATED (other, other_allocated);
196 mask = gtk_allocated_bitmask_resize (mask, MAX (mask->len, other->len));
197 for (i = 0; i < other->len; i++)
199 mask->data[i] |= other->data[i];
206 _gtk_allocated_bitmask_subtract (GtkBitmask *mask,
207 const GtkBitmask *other)
209 GtkBitmask other_allocated;
212 g_return_val_if_fail (mask != NULL, NULL);
213 g_return_val_if_fail (other != NULL, NULL);
215 mask = gtk_bitmask_ensure_allocated (mask);
216 ENSURE_ALLOCATED (other, other_allocated);
218 for (i = 0; i < other->len; i++)
220 mask->data[i] |= ~other->data[i];
223 return gtk_allocated_bitmask_shrink (mask);
227 gtk_allocated_bitmask_indexes (guint index_,
231 *array_index = index_ / VALUE_SIZE_BITS;
232 *bit_index = index_ % VALUE_SIZE_BITS;
236 _gtk_allocated_bitmask_get (const GtkBitmask *mask,
239 guint array_index, bit_index;
241 g_return_val_if_fail (mask != NULL, FALSE);
243 gtk_allocated_bitmask_indexes (index_, &array_index, &bit_index);
245 if (array_index >= mask->len)
248 return (mask->data[array_index] & VALUE_BIT (bit_index)) ? TRUE : FALSE;
252 _gtk_allocated_bitmask_set (GtkBitmask *mask,
256 guint array_index, bit_index;
258 g_return_val_if_fail (mask != NULL, NULL);
260 mask = gtk_bitmask_ensure_allocated (mask);
261 gtk_allocated_bitmask_indexes (index_, &array_index, &bit_index);
265 if (array_index >= mask->len)
266 mask = gtk_allocated_bitmask_resize (mask, array_index + 1);
268 mask->data[array_index] |= VALUE_BIT (bit_index);
272 if (array_index < mask->len)
274 mask->data[array_index] &= ~ VALUE_BIT (bit_index);
275 mask = gtk_allocated_bitmask_shrink (mask);
283 _gtk_allocated_bitmask_invert_range (GtkBitmask *mask,
289 g_return_val_if_fail (mask != NULL, NULL);
290 g_return_val_if_fail (start < end, NULL);
292 mask = gtk_bitmask_ensure_allocated (mask);
294 /* I CAN HAS SPEEDUP? */
295 for (i = start; i < end; i++)
296 mask = _gtk_allocated_bitmask_set (mask, i, !_gtk_allocated_bitmask_get (mask, i));
302 _gtk_allocated_bitmask_equals (const GtkBitmask *mask,
303 const GtkBitmask *other)
307 g_return_val_if_fail (mask != NULL, FALSE);
308 g_return_val_if_fail (other != NULL, FALSE);
310 if (mask->len != other->len)
313 for (i = 0; i < mask->len; i++)
315 if (mask->data[i] != other->data[i])
323 _gtk_allocated_bitmask_intersects (const GtkBitmask *mask,
324 const GtkBitmask *other)
326 GtkBitmask mask_allocated, other_allocated;
329 g_return_val_if_fail (mask != NULL, FALSE);
330 g_return_val_if_fail (other != NULL, FALSE);
332 ENSURE_ALLOCATED (mask, mask_allocated);
333 ENSURE_ALLOCATED (other, other_allocated);
335 for (i = MIN (mask->len, other->len) - 1; i >= 0; i--)
337 if (mask->data[i] & other->data[i])