[gtk/wip/chergert/fix-class-private-data-usage: 1/3] gtk: add bitarray for use by widget muxer
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/fix-class-private-data-usage: 1/3] gtk: add bitarray for use by widget muxer
- Date: Fri, 20 Mar 2020 16:24:38 +0000 (UTC)
commit 8d1588a0de21e46711b3991a54380121d634881b
Author: Christian Hergert <chergert redhat com>
Date: Fri Mar 20 09:15:29 2020 -0700
gtk: add bitarray for use by widget muxer
We need a compact bitarray to track widget enabled state without having
to allocate a gboolean for each action. Additionally, the common case (of
up to 64 actions in a single widget) requires no additional allocation
beyond the embedding of the BitArray.
The bit array dynamically grows based on the position requested. You can
also set a default value for the bits so that consumers do not need to
invert the value for cases where TRUE is the default (such as the use by
GtkActionMuxer).
gtk/bitarray.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gtk/bitarray.h | 40 +++++++++++++++
gtk/meson.build | 1 +
3 files changed, 191 insertions(+)
---
diff --git a/gtk/bitarray.c b/gtk/bitarray.c
new file mode 100644
index 0000000000..05a0bde88c
--- /dev/null
+++ b/gtk/bitarray.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2020 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "bitarray.h"
+
+#define BIT_ARRAY_MASK(onoff) (onoff ? (gpointer)(~(guintptr)0) : NULL)
+
+static void
+bit_array_expand_from_static (BitArray *ba,
+ guint n_bytes)
+{
+ guint8 *old = ba->data;
+ gpointer default_value;
+
+ ba->data = g_malloc (n_bytes);
+ memcpy (ba->data, &old, GLIB_SIZEOF_VOID_P);
+
+ default_value = BIT_ARRAY_MASK (ba->default_value);
+ for (guint i = ba->n_bytes; i < n_bytes; i++)
+ ba->data[i] = GPOINTER_TO_UINT (default_value) & 0xFF;
+
+ ba->n_bytes = n_bytes;
+}
+
+static void
+bit_array_expand_realloc (BitArray *ba,
+ guint n_bytes)
+{
+ gpointer default_value;
+
+ ba->data = g_realloc (ba->data, n_bytes);
+
+ default_value = BIT_ARRAY_MASK (ba->default_value);
+ for (guint i = ba->n_bytes; i < n_bytes; i++)
+ ba->data[i] = GPOINTER_TO_UINT (default_value) & 0xFF;
+
+ ba->n_bytes = n_bytes;
+}
+
+void
+bit_array_init (BitArray *ba,
+ gboolean default_value)
+{
+ ba->default_value = !!default_value;
+ ba->n_bytes = GLIB_SIZEOF_VOID_P;
+ ba->data = BIT_ARRAY_MASK (default_value);
+}
+
+void
+bit_array_clear (BitArray *ba)
+{
+ if (ba->n_bytes != GLIB_SIZEOF_VOID_P)
+ g_free (ba->data);
+}
+
+void
+bit_array_set (BitArray *ba,
+ guint position,
+ gboolean value)
+{
+ guint8 *buf;
+ guint target = position >> 3;
+
+ if (target >= ba->n_bytes)
+ {
+ if (ba->n_bytes == GLIB_SIZEOF_VOID_P)
+ bit_array_expand_from_static (ba, target + 1);
+ else
+ bit_array_expand_realloc (ba, target + 1);
+ }
+
+ if (ba->n_bytes == GLIB_SIZEOF_VOID_P)
+ buf = (gpointer)&ba->data;
+ else
+ buf = ba->data;
+
+ if (value)
+ buf[target] |= (1U << (position & 0x7));
+ else
+ buf[target] &= ~(1U << (position & 0x7));
+}
+
+gboolean
+bit_array_get (BitArray *ba,
+ guint position)
+{
+ guint8 *buf;
+ guint target = position >> 3;
+
+ if (target >= ba->n_bytes)
+ return ba->default_value;
+
+ if (ba->n_bytes == GLIB_SIZEOF_VOID_P)
+ buf = (gpointer)&ba->data;
+ else
+ buf = ba->data;
+
+ return (buf[target] >> (position & 0x7)) & 0x1;
+}
+
+#if 0
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ BitArray ba;
+
+ bit_array_init (&ba, FALSE);
+ g_assert_true (ba.data == NULL);
+ for (guint i = 0; i < 100; i++)
+ g_assert_cmpint (bit_array_get (&ba, i), ==, FALSE);
+ g_assert_true (ba.data == NULL);
+ bit_array_clear (&ba);
+
+ bit_array_init (&ba, TRUE);
+ g_assert_true (ba.data == BIT_ARRAY_MASK(TRUE));
+ for (guint i = 0; i < 100; i++)
+ g_assert_cmpint (bit_array_get (&ba, i), ==, TRUE);
+ g_assert_true (ba.data == BIT_ARRAY_MASK(TRUE));
+ bit_array_clear (&ba);
+
+ bit_array_init (&ba, TRUE);
+ g_assert_true (ba.data == BIT_ARRAY_MASK(TRUE));
+ for (guint i = 0; i < 1024; i++)
+ {
+ g_assert_cmpint (bit_array_get (&ba, i), ==, TRUE);
+ bit_array_set (&ba, i, FALSE);
+ g_assert_cmpint (bit_array_get (&ba, i), ==, FALSE);
+ }
+ for (guint i = 0; i < 1024; i++)
+ g_assert_cmpint (bit_array_get (&ba, i), ==, FALSE);
+ for (guint i = 0; i < (1024/8); i++)
+ g_assert_false (ba.data[i]);
+ bit_array_clear (&ba);
+}
+#endif
diff --git a/gtk/bitarray.h b/gtk/bitarray.h
new file mode 100644
index 0000000000..8d18289fd2
--- /dev/null
+++ b/gtk/bitarray.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef __BITARRAY_H__
+#define __BITARRAY_H__
+
+#include <glib.h>
+
+typedef struct _BitArray
+{
+ /*< private >*/
+ guint32 default_value : 1;
+ guint32 n_bytes : 31;
+ guint8 *data;
+} BitArray;
+
+void bit_array_init (BitArray *ba,
+ gboolean default_value);
+void bit_array_clear (BitArray *ba);
+void bit_array_set (BitArray *ba,
+ guint position,
+ gboolean value);
+gboolean bit_array_get (BitArray *ba,
+ guint position);
+
+#endif /* __BITARRAY_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index bf7e08a06c..3f3e517f49 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -14,6 +14,7 @@ gtk_cargs = [
# List of sources that do not contain public API, and should not be
# introspected
gtk_private_sources = files([
+ 'bitarray.c',
'fallback-c89.c',
'fnmatch.c',
'tools/gdkpixbufutils.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]