[gtk/wip/otte/bitset: 2/23] Add GtkBitset
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/bitset: 2/23] Add GtkBitset
- Date: Fri, 26 Jun 2020 03:16:59 +0000 (UTC)
commit 020b0791b1ba843be58e307af7e4390e4a352d3c
Author: Benjamin Otte <otte redhat com>
Date: Wed Jun 10 08:14:02 2020 +0200
Add GtkBitset
gtk/gtk.h | 1 +
gtk/gtkbitset.c | 843 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkbitset.h | 151 ++++++++++
gtk/gtktypes.h | 1 +
gtk/meson.build | 2 +
5 files changed, 998 insertions(+)
---
diff --git a/gtk/gtk.h b/gtk/gtk.h
index b7600866f9..22964a4887 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -47,6 +47,7 @@
#include <gtk/gtkaspectframe.h>
#include <gtk/gtkassistant.h>
#include <gtk/gtkbinlayout.h>
+#include <gtk/gtkbitset.h>
#include <gtk/gtkbookmarklist.h>
#include <gtk/gtkborder.h>
#include <gtk/gtkboxlayout.h>
diff --git a/gtk/gtkbitset.c b/gtk/gtkbitset.c
new file mode 100644
index 0000000000..7c02c7bf1c
--- /dev/null
+++ b/gtk/gtkbitset.c
@@ -0,0 +1,843 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkbitset.h"
+
+#include "roaring.c"
+
+/**
+ * GtkBitset: (ref-func gtk_bitset_ref) (unref-func gtk_bitset_unref)
+ *
+ * The `GtkBitset` structure contains only private data.
+ */
+struct _GtkBitset
+{
+ int ref_count;
+ roaring_bitmap_t roaring;
+};
+
+
+G_DEFINE_BOXED_TYPE (GtkBitset, gtk_bitset,
+ gtk_bitset_ref,
+ gtk_bitset_unref)
+
+/**
+ * gtk_bitset_ref:
+ * @self: (allow-none): a #GtkBitset
+ *
+ * Acquires a reference on the given #GtkBitset.
+ *
+ * Returns: (transfer none): the #GtkBitset with an additional reference
+ */
+GtkBitset *
+gtk_bitset_ref (GtkBitset *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ self->ref_count += 1;
+
+ return self;
+}
+
+/**
+ * gtk_bitset_unref:
+ * @self: (allow-none): a #GtkBitset
+ *
+ * Releases a reference on the given #GtkBitset.
+ *
+ * If the reference was the last, the resources associated to the @self are
+ * freed.
+ */
+void
+gtk_bitset_unref (GtkBitset *self)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (self->ref_count > 0);
+
+ self->ref_count -= 1;
+ if (self->ref_count > 0)
+ return;
+
+ ra_clear (&self->roaring.high_low_container);
+ g_slice_free (GtkBitset, self);
+}
+
+/**
+ * gtk_bitset_contains:
+ * @self: a #GtkBitset
+ * @value: the value to check
+ *
+ * Checks if the given @value has been added to @bitset
+ *
+ * Returns: %TRUE if @self contains @value
+ **/
+gboolean
+gtk_bitset_contains (const GtkBitset *self,
+ guint value)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return roaring_bitmap_contains (&self->roaring, value);
+}
+
+/**
+ * gtk_bitset_is_empty:
+ * @self: a #GtkBitset
+ *
+ * Check if no value is contained in bitset.
+ *
+ * Returns: %TRUE if @self is empty
+ **/
+gboolean
+gtk_bitset_is_empty (const GtkBitset *self)
+{
+ g_return_val_if_fail (self != NULL, TRUE);
+
+ return roaring_bitmap_is_empty (&self->roaring);
+}
+
+/**
+ * gtk_bitset_equals:
+ * @self: a #GtkBitset
+ * @other: another #GtkBitset
+ *
+ * Returns %TRUE if @self and @other contain the same values.
+ *
+ * Returns: %TRUE if @self and @other contain the same values
+ **/
+gboolean
+gtk_bitset_equals (const GtkBitset *self,
+ const GtkBitset *other)
+{
+ g_return_val_if_fail (self != NULL, other == NULL);
+ g_return_val_if_fail (other != NULL, FALSE);
+
+ if (self == other)
+ return TRUE;
+
+ return roaring_bitmap_equals (&self->roaring, &other->roaring);
+}
+
+/**
+ * gtk_bitset_get_minimum:
+ * @self: a #GtkBitset
+ *
+ * Returns the smallest value in @self. If @self is empty,
+ * G_MAXUINT is returned.
+ *
+ * Returns: The smallest value in @self
+ **/
+guint
+gtk_bitset_get_minimum (const GtkBitset *self)
+{
+ g_return_val_if_fail (self != NULL, G_MAXUINT);
+
+ return roaring_bitmap_minimum (&self->roaring);
+}
+
+/**
+ * gtk_bitset_get_maximum:
+ * @self: a #GtkBitset
+ *
+ * Returns the largest value in @self. If @self is empty,
+ * 0 is returned.
+ *
+ * Returns: The largest value in @self
+ **/
+guint
+gtk_bitset_get_maximum (const GtkBitset *self)
+{
+ g_return_val_if_fail (self != NULL, 0);
+
+ return roaring_bitmap_maximum (&self->roaring);
+}
+
+/**
+ * gtk_bitset_new_empty:
+ *
+ * Creates a new empty bitset.
+ *
+ * Returns: A new empty bitset.
+ **/
+GtkBitset *
+gtk_bitset_new_empty (void)
+{
+ GtkBitset *self;
+
+ self = g_slice_new0 (GtkBitset);
+
+ self->ref_count = 1;
+
+ ra_init (&self->roaring.high_low_container);
+
+ return self;
+}
+
+/**
+ * gtk_bitset_copy:
+ * @self: a #GtkBitset
+ *
+ * Creates a copy of @self.
+ *
+ * Returns: (transfer full) A new bitset that contains the same
+ * values as @self
+ **/
+GtkBitset *
+gtk_bitset_copy (const GtkBitset *self)
+{
+ GtkBitset *copy;
+
+ g_return_val_if_fail (self != NULL, NULL);
+
+ copy = gtk_bitset_new_empty ();
+ roaring_bitmap_overwrite (©->roaring, &self->roaring);
+
+ return copy;
+}
+
+/**
+ * gtk_bitset_remove_all:
+ * @self: a #GtkBitset
+ *
+ * Removes all values from the bitset so that it is empty again.
+ **/
+void
+gtk_bitset_remove_all (GtkBitset *self)
+{
+ g_return_if_fail (self != NULL);
+
+ roaring_bitmap_clear (&self->roaring);
+}
+
+/**
+ * gtk_bitset_add:
+ * @self: a #GtkBitset
+ * @value: value to add
+ *
+ * Adds @value to @self if it wasn't part of it before.
+ *
+ * Returns: %TRUE if @value was not part of @self and @self
+ * was changed.
+ **/
+gboolean
+gtk_bitset_add (GtkBitset *self,
+ guint value)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return roaring_bitmap_add_checked (&self->roaring, value);
+}
+
+/**
+ * gtk_bitset_remove:
+ * @self: a #GtkBitset
+ * @value: value to add
+ *
+ * Adds @value to @self if it wasn't part of it before.
+ *
+ * Returns: %TRUE if @value was part of @self and @self
+ * was changed.
+ **/
+gboolean
+gtk_bitset_remove (GtkBitset *self,
+ guint value)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return roaring_bitmap_remove_checked (&self->roaring, value);
+}
+
+/**
+ * gtk_bitset_add_range:
+ * @self: a #GtkBitset
+ * @start: first value to add
+ * @n_items: number of consecutive values to add
+ *
+ * Adds all values from @start (inclusive) to @start + @n_items (exclusive)
+ * in @self.
+ **/
+void
+gtk_bitset_add_range (GtkBitset *self,
+ guint start,
+ guint n_items)
+{
+ g_return_if_fail (self != NULL);
+
+ if (n_items == 0)
+ return;
+
+ /* overflow check, the == 0 is to allow add_range(G_MAXUINT, 1); */
+ g_return_if_fail (start + n_items == 0 || start + n_items > start);
+
+ roaring_bitmap_add_range_closed (&self->roaring, start, start + n_items - 1);
+}
+
+/**
+ * gtk_bitset_remove_range:
+ * @self: a #GtkBitset
+ * @start: first value to remove
+ * @n_items: number of consecutive values to remove
+ *
+ * Removes all values from @start (inclusive) to @start + @n_items (exclusive)
+ * in @self.
+ **/
+void
+gtk_bitset_remove_range (GtkBitset *self,
+ guint start,
+ guint n_items)
+{
+ g_return_if_fail (self != NULL);
+
+ if (n_items == 0)
+ return;
+
+ /* overflow check, the == 0 is to allow add_range(G_MAXUINT, 1); */
+ g_return_if_fail (start + n_items == 0 || start + n_items > start);
+
+ roaring_bitmap_remove_range_closed (&self->roaring, start, start + n_items - 1);
+}
+
+/**
+ * gtk_bitset_add_range_closed:
+ * @self: a #GtkBitset
+ * @first: first value to add
+ * @last: last value to add
+ *
+ * Adds the closed range [@first, @last], so @first, @last and all values inbetween.
+ * @first must be smaller than @last.
+ **/
+void
+gtk_bitset_add_range_closed (GtkBitset *self,
+ guint first,
+ guint last)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (first <= last);
+
+ roaring_bitmap_add_range_closed (&self->roaring, first, last);
+}
+
+/**
+ * gtk_bitset_remove_range_closed:
+ * @self: a #GtkBitset
+ * @first: first value to remove
+ * @last: last value to remove
+ *
+ * Removes the closed range [@first, @last], so @first, @last and all values inbetween.
+ * @first must be smaller than @last.
+ **/
+void
+gtk_bitset_remove_range_closed (GtkBitset *self,
+ guint first,
+ guint last)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (first <= last);
+
+ roaring_bitmap_remove_range_closed (&self->roaring, first, last);
+}
+
+/**
+ * gtk_bitset_add_rectangle:
+ * @self: a #GtkBitset
+ * @start: first value to add
+ * @width: width of the rectangle
+ * @height: height of the rectangle
+ * @stride: rowstride of the rectangle
+ *
+ * Interprets the values as a 2-dimensional boolean grid with the given @stride
+ * and inside that grid, adds a rectangle with the given @width and @height.
+ **/
+void
+gtk_bitset_add_rectangle (GtkBitset *self,
+ guint start,
+ guint width,
+ guint height,
+ guint stride)
+{
+ guint i;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (width <= stride);
+ g_return_if_fail (G_MAXUINT - start >= height * stride);
+
+ if (width == 0 || height == 0)
+ return;
+
+ for (i = 0; i < height; i++)
+ gtk_bitset_add_range (self, i * stride + start, width);
+}
+
+/**
+ * gtk_bitset_remove_rectangle:
+ * @self: a #GtkBitset
+ * @start: first value to remove
+ * @width: width of the rectangle
+ * @height: height of the rectangle
+ * @stride: rowstride of the rectangle
+ *
+ * Interprets the values as a 2-dimensional boolean grid with the given @stride
+ * and inside that grid, removes a rectangle with the given @width and @height.
+ **/
+void
+gtk_bitset_remove_rectangle (GtkBitset *self,
+ guint start,
+ guint width,
+ guint height,
+ guint stride)
+{
+ guint i;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (width <= stride);
+ g_return_if_fail (G_MAXUINT - start >= height * stride);
+
+ if (width == 0 || height == 0)
+ return;
+
+ for (i = 0; i < height; i++)
+ gtk_bitset_remove_range (self, i * stride + start, width);
+}
+
+/**
+ * gtk_bitset_union:
+ * @self: a #GtkBitset
+ * @other: the #GtkBitset to union with
+ *
+ * Sets @self to be the union of @self and @other, that is add all values
+ * from @other into @self that weren't part of it.
+ *
+ * It is allowed for @self and @other to be the same bitset. Nothing will
+ * happen in that case.
+ **/
+void
+gtk_bitset_union (GtkBitset *self,
+ const GtkBitset *other)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (other != NULL);
+
+ if (self == other)
+ return;
+
+ roaring_bitmap_or_inplace (&self->roaring, &other->roaring);
+}
+
+/**
+ * gtk_bitset_intersect:
+ * @self: a #GtkBitset
+ * @other: the #GtkBitset to intersect with
+ *
+ * Sets @self to be the intersection of @self and @other, that is remove all values
+ * from @self that are not part of @other.
+ *
+ * It is allowed for @self and @other to be the same bitset. Nothing will
+ * happen in that case.
+ **/
+void
+gtk_bitset_intersect (GtkBitset *self,
+ const GtkBitset *other)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (other != NULL);
+
+ if (self == other)
+ return;
+
+ roaring_bitmap_and_inplace (&self->roaring, &other->roaring);
+}
+
+/**
+ * gtk_bitset_subtract:
+ * @self: a #GtkBitset
+ * @other: the #GtkBitset to subtract
+ *
+ * Sets @self to be the subtraction of @other from @self, that is remove
+ * all values from @self that are part of @other.
+ *
+ * It is allowed for @self and @other to be the same bitset. The bitset
+ * will be emptied in that case.
+ **/
+void
+gtk_bitset_subtract (GtkBitset *self,
+ const GtkBitset *other)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (other != NULL);
+
+ if (self == other)
+ {
+ roaring_bitmap_clear (&self->roaring);
+ return;
+ }
+
+ roaring_bitmap_andnot_inplace (&self->roaring, &other->roaring);
+}
+
+/**
+ * gtk_bitset_difference:
+ * @self: a #GtkBitset
+ * @other: the #GtkBitset to compute the difference from
+ *
+ * Sets @self to be the symmetric difference of @self and @other, that
+ * is set @self to contain all values that were either contained in @self
+ * or in @other, but not in both.
+ * This operation is also called an XOR.
+ *
+ * It is allowed for @self and @other to be the same bitset. The bitset
+ * will be emptied in that case.
+ **/
+void
+gtk_bitset_difference (GtkBitset *self,
+ const GtkBitset *other)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (other != NULL);
+
+ if (self == other)
+ {
+ roaring_bitmap_clear (&self->roaring);
+ return;
+ }
+
+ roaring_bitmap_xor_inplace (&self->roaring, &other->roaring);
+}
+
+/**
+ * gtk_bitset_shift_left:
+ * @self: a $GtkBitset
+ * @amount: amount to shift all values to the left
+ *
+ * Shifts all values in @self to the left by @amount. Values
+ * smaller than @amount are discarded.
+ **/
+void
+gtk_bitset_shift_left (GtkBitset *self,
+ guint amount)
+{
+ GtkBitset *original;
+ GtkBitsetIter iter;
+ guint value;
+ gboolean loop;
+
+ g_return_if_fail (self != NULL);
+
+ if (amount == 0)
+ return;
+
+ original = gtk_bitset_copy (self);
+ gtk_bitset_remove_all (self);
+
+ for (loop = gtk_bitset_iter_init_at (&iter, original, amount, &value);
+ loop;
+ loop = gtk_bitset_iter_next (&iter, &value))
+ {
+ gtk_bitset_add (self, value - amount);
+ }
+
+ gtk_bitset_unref (original);
+}
+
+/**
+ * gtk_bitset_shift_left:
+ * @self: a $GtkBitset
+ * @amount: amount to shift all values to the right
+ *
+ * Shifts all values in @self to the right by @amount. Values
+ * that end up too large to be held in a #guint are discarded.
+ **/
+void
+gtk_bitset_shift_right (GtkBitset *self,
+ guint amount)
+{
+ GtkBitset *original;
+ GtkBitsetIter iter;
+ guint value;
+ gboolean loop;
+
+ g_return_if_fail (self != NULL);
+
+ if (amount == 0)
+ return;
+
+ original = gtk_bitset_copy (self);
+ gtk_bitset_remove_all (self);
+
+ for (loop = gtk_bitset_iter_init_at (&iter, original, amount, &value);
+ loop && value >= G_MAXUINT - amount;
+ loop = gtk_bitset_iter_next (&iter, &value))
+ {
+ gtk_bitset_add (self, value + amount);
+ }
+
+ gtk_bitset_unref (original);
+}
+
+/**
+ * gtk_bitset_slice:
+ * @self: a #GtkBitset
+ * @position: position at which to slice
+ * @removed: number of values to remove
+ * @added: number of values to add
+ *
+ * This is a support function for #GListModel handling, by mirroring
+ * the #GlistModel::items-changed signal.
+ *
+ * First, it "cuts" the values from @position to @removed from
+ * the bitset. That is, it removes all those values and shifts
+ * all larger values to the left by @removed places.
+ *
+ * Then, it "pastes" new room into the bitset by shifting all values
+ * larger than @position by @added spaces to the right. This frees
+ * up space that can then be filled using
+ **/
+void
+gtk_bitset_slice (GtkBitset *self,
+ guint position,
+ guint removed,
+ guint added)
+{
+ g_return_if_fail (self != NULL);
+ /* overflow */
+ g_return_if_fail (position + removed >= position);
+ g_return_if_fail (position + added >= position);
+
+ gtk_bitset_remove_range (self, position, removed);
+
+ if (removed != added)
+ {
+ GtkBitset *shift = gtk_bitset_copy (self);
+
+ gtk_bitset_remove_range (shift, 0, position);
+ gtk_bitset_remove_range (self, position, G_MAXUINT - position + 1);
+ if (added > removed)
+ gtk_bitset_shift_right (shift, added - removed);
+ else
+ gtk_bitset_shift_left (shift, removed - added);
+ gtk_bitset_union (self, shift);
+ gtk_bitset_unref (shift);
+ }
+}
+
+G_STATIC_ASSERT (sizeof (GtkBitsetIter) >= sizeof (roaring_uint32_iterator_t));
+
+/**
+ * gtk_bitset_iter_init_first:
+ * @iter: (out): a pointer to a preallocated #GtkBitsetIter
+ * @set: a #GtkBitset
+ * @value: (out) (optional): Set to the first value in @set
+ *
+ * Initializes an iterator for @set and points it to the first
+ * value in @set. If @set is empty, %FALSE is returned and @value is set to
+ * %G_MAXUINT.
+ *
+ * Returns: %TRUE if a @set isn't empty.
+ **/
+gboolean
+gtk_bitset_iter_init_first (GtkBitsetIter *iter,
+ const GtkBitset *set,
+ guint *value)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (set != NULL, FALSE);
+
+ roaring_init_iterator (&set->roaring, riter);
+
+ if (value)
+ *value = riter->has_value ? riter->current_value : 0;
+
+ return riter->has_value;
+}
+
+/**
+ * gtk_bitset_iter_init_last:
+ * @iter: (out): a pointer to a preallocated #GtkBitsetIter
+ * @set: a #GtkBitset
+ * @value: (out) (optional): Set to the last value in @set
+ *
+ * Initializes an iterator for @set and points it to the last
+ * value in @set. If @set is empty, %FALSE is returned.
+ *
+ * Returns: %TRUE if a @set isn't empty.
+ **/
+gboolean
+gtk_bitset_iter_init_last (GtkBitsetIter *iter,
+ const GtkBitset *set,
+ guint *value)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (set != NULL, FALSE);
+
+ roaring_init_iterator_last (&set->roaring, riter);
+
+ if (value)
+ *value = riter->has_value ? riter->current_value : 0;
+
+ return riter->has_value;
+}
+
+/**
+ * gtk_bitset_iter_init_at:
+ * @iter: a #GtkBitsetIter
+ * @target: target value to start iterating at
+ * @value: (out) (optional): Set to the found value in @set
+ *
+ * Initializes @iter to point to @target. If @target is not found, finds
+ * the next value after it. If no value >= @target exists in @set, this
+ * function returns %FALSE.
+ *
+ * Returns: %TRUE if a value was found.
+ **/
+gboolean
+gtk_bitset_iter_init_at (GtkBitsetIter *iter,
+ const GtkBitset *set,
+ guint target,
+ guint *value)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (set != NULL, FALSE);
+
+ roaring_init_iterator (&set->roaring, riter);
+ if (!roaring_move_uint32_iterator_equalorlarger (riter, target))
+ {
+ if (value)
+ *value = 0;
+ return FALSE;
+ }
+
+ if (value)
+ *value = riter->current_value;
+
+ return TRUE;
+}
+
+/**
+ * gtk_bitset_iter_next:
+ * @iter: (out): a pointer to a valid #GtkBitsetIter
+ * @value: (out) (optional): Set to the next value
+ *
+ * Moves @iter to the next value in the set. If it was already
+ * pointing to the last value in the set, %FALSE is returned and
+ * @iter is invalidated.
+ *
+ * Returns: %TRUE if a next value existed
+ **/
+gboolean
+gtk_bitset_iter_next (GtkBitsetIter *iter,
+ guint *value)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ if (!roaring_advance_uint32_iterator (riter))
+ {
+ if (value)
+ *value = 0;
+ return FALSE;
+ }
+
+ if (value)
+ *value = riter->current_value;
+
+ return TRUE;
+}
+
+/**
+ * gtk_bitset_iter_previous:
+ * @iter: (out): a pointer to a valid #GtkBitsetIter
+ * @value: (out) (optional): Set to the previous value
+ *
+ * Moves @iter to the previous value in the set. If it was already
+ * pointing to the first value in the set, %FALSE is returned and
+ * @iter is invalidated.
+ *
+ * Returns: %TRUE if a previous value existed
+ **/
+gboolean
+gtk_bitset_iter_previous (GtkBitsetIter *iter,
+ guint *value)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ if (!roaring_previous_uint32_iterator (riter))
+ {
+ if (value)
+ *value = 0;
+ return FALSE;
+ }
+
+ if (value)
+ *value = riter->current_value;
+
+ return TRUE;
+}
+
+/**
+ * gtk_bitset_iter_get_value:
+ * @iter: a #GtkBitsetIter
+ *
+ * Gets the current value that @iter points to.
+ *
+ * If @iter is not valid and gtk_bitset_iter_is_valid() returns
+ * %FALSE, this function returns 0.
+ *
+ * Returns: The current value pointer to by @iter
+ **/
+guint
+gtk_bitset_iter_get_value (const GtkBitsetIter *iter)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, 0);
+
+ if (!riter->has_value)
+ return 0;
+
+ return riter->current_value;
+}
+
+/**
+ * gtk_bitset_iter_is_valid:
+ * @iter: a #GtkBitsetIter
+ *
+ * Checks if @iter points to a valid value
+ *
+ * Returns: %TRUE if @iter points to a valid value
+ **/
+gboolean
+gtk_bitset_iter_is_valid (const GtkBitsetIter *iter)
+{
+ roaring_uint32_iterator_t *riter = (roaring_uint32_iterator_t *) iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ return riter->has_value;
+}
+
diff --git a/gtk/gtkbitset.h b/gtk/gtkbitset.h
new file mode 100644
index 0000000000..fc26e0d7de
--- /dev/null
+++ b/gtk/gtkbitset.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+
+#ifndef __GTK_BITSET_H__
+#define __GTK_BITSET_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtktypes.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BITSET (gtk_bitset_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_bitset_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkBitset * gtk_bitset_ref (GtkBitset *self);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_unref (GtkBitset *self);
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_contains (const GtkBitset *self,
+ guint value);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_is_empty (const GtkBitset *self);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_equals (const GtkBitset *self,
+ const GtkBitset *other);
+GDK_AVAILABLE_IN_ALL
+guint gtk_bitset_get_minimum (const GtkBitset *self);
+GDK_AVAILABLE_IN_ALL
+guint gtk_bitset_get_maximum (const GtkBitset *self);
+
+GDK_AVAILABLE_IN_ALL
+GtkBitset * gtk_bitset_new_empty (void);
+GDK_AVAILABLE_IN_ALL
+GtkBitset * gtk_bitset_copy (const GtkBitset *self);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_remove_all (GtkBitset *self);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_add (GtkBitset *self,
+ guint value);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_remove (GtkBitset *self,
+ guint value);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_add_range (GtkBitset *self,
+ guint start,
+ guint n_items);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_remove_range (GtkBitset *self,
+ guint start,
+ guint n_items);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_add_range_closed (GtkBitset *self,
+ guint first,
+ guint last);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_remove_range_closed (GtkBitset *self,
+ guint first,
+ guint last);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_add_rectangle (GtkBitset *self,
+ guint start,
+ guint width,
+ guint height,
+ guint stride);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_remove_rectangle (GtkBitset *self,
+ guint start,
+ guint width,
+ guint height,
+ guint stride);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_union (GtkBitset *self,
+ const GtkBitset *other);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_intersect (GtkBitset *self,
+ const GtkBitset *other);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_subtract (GtkBitset *self,
+ const GtkBitset *other);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_difference (GtkBitset *self,
+ const GtkBitset *other);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_shift_left (GtkBitset *self,
+ guint amount);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_shift_right (GtkBitset *self,
+ guint amount);
+GDK_AVAILABLE_IN_ALL
+void gtk_bitset_slice (GtkBitset *self,
+ guint position,
+ guint removed,
+ guint added);
+
+typedef struct {gpointer private_data[10]; } GtkBitsetIter;
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_iter_init_first (GtkBitsetIter *iter,
+ const GtkBitset *set,
+ guint *value);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_iter_init_last (GtkBitsetIter *iter,
+ const GtkBitset *set,
+ guint *value);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_iter_init_at (GtkBitsetIter *iter,
+ const GtkBitset *set,
+ guint target,
+ guint *value);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_iter_next (GtkBitsetIter *iter,
+ guint *value);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_iter_previous (GtkBitsetIter *iter,
+ guint *value);
+GDK_AVAILABLE_IN_ALL
+guint gtk_bitset_iter_get_value (const GtkBitsetIter *iter);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bitset_iter_is_valid (const GtkBitsetIter *iter);
+
+
+
+G_END_DECLS
+
+#endif /* __GTK_BITSET_H__ */
diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h
index f8e68a0e07..9c3f4fe2ed 100644
--- a/gtk/gtktypes.h
+++ b/gtk/gtktypes.h
@@ -34,6 +34,7 @@
G_BEGIN_DECLS
typedef struct _GtkAdjustment GtkAdjustment;
+typedef struct _GtkBitset GtkBitset;
typedef struct _GtkBuilder GtkBuilder;
typedef struct _GtkBuilderScope GtkBuilderScope;
typedef struct _GtkClipboard GtkClipboard;
diff --git a/gtk/meson.build b/gtk/meson.build
index 83048902a7..3ab5ce8d20 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -164,6 +164,7 @@ gtk_public_sources = files([
'gtkaspectframe.c',
'gtkassistant.c',
'gtkbinlayout.c',
+ 'gtkbitset.c',
'gtkbookmarklist.c',
'gtkborder.c',
'gtkboxlayout.c',
@@ -450,6 +451,7 @@ gtk_public_headers = files([
'gtkaspectframe.h',
'gtkassistant.h',
'gtkbinlayout.h',
+ 'gtkbitset.h',
'gtkbookmarklist.h',
'gtkborder.h',
'gtkbox.h',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]