summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Roberts <neil@linux.intel.com>2011-11-02 13:41:32 +0000
committerNeil Roberts <neil@linux.intel.com>2011-11-16 16:32:00 +0000
commitd70699157979cf19a5598f27fd071a8fd05f2840 (patch)
tree438831be105ab22462ec72119a7cea2d03365b98
parentdbc31b70cc790833d8926ebad3e03c2d236965ae (diff)
downloadcogl-d70699157979cf19a5598f27fd071a8fd05f2840.tar.gz
cogl-flags: Add some macros to help iterate the bits
This adds some macros to iterate over all the bits set in an array of flags. The macros are a bit awkward because it tries to avoid using a callback pointer so that the code is inlined. cogl_bitmask is now using these macros as well so that the logic can be shared. Reviewed-by: Robert Bragg <robert@linux.intel.com>
-rw-r--r--cogl-pango/Makefile.am1
-rw-r--r--cogl/cogl-bitmask.c36
-rw-r--r--cogl/cogl-flags.h36
3 files changed, 48 insertions, 25 deletions
diff --git a/cogl-pango/Makefile.am b/cogl-pango/Makefile.am
index 6917c1cd..5ee1fabb 100644
--- a/cogl-pango/Makefile.am
+++ b/cogl-pango/Makefile.am
@@ -40,6 +40,7 @@ INCLUDES = \
-DCLUTTER_COMPILATION \
-DG_LOG_DOMAIN=\"CoglPango\" \
-I$(top_srcdir)/cogl \
+ -I$(top_builddir)/cogl \
-I$(top_srcdir)/cogl/winsys \
-I$(top_srcdir) \
-I$(top_builddir)
diff --git a/cogl/cogl-bitmask.c b/cogl/cogl-bitmask.c
index 1fe21983..ec69625d 100644
--- a/cogl/cogl-bitmask.c
+++ b/cogl/cogl-bitmask.c
@@ -33,6 +33,7 @@
#include "cogl-bitmask.h"
#include "cogl-util.h"
+#include "cogl-flags.h"
/* This code assumes that we can cast an unsigned long to a pointer
and back without losing any data */
@@ -236,41 +237,26 @@ _cogl_bitmask_foreach (const CoglBitmask *bitmask,
if (_cogl_bitmask_has_array (bitmask))
{
GArray *array = (GArray *) *bitmask;
- int array_index;
+ const unsigned long *values = &g_array_index (array, unsigned long, 0);
+ int bit_num;
- for (array_index = 0; array_index < array->len; array_index++)
+ COGL_FLAGS_FOREACH_START (values, array->len, bit_num)
{
- unsigned long mask =
- g_array_index (array, unsigned long, array_index);
- int bit = 0;
-
- while (mask)
- {
- int next_bit = _cogl_util_ffsl (mask);
-
- bit += next_bit;
- mask >>= next_bit;
-
- if (!func (array_index * sizeof (unsigned long) * 8 + bit - 1,
- user_data))
- return;
- }
+ if (!func (bit_num, user_data))
+ return;
}
+ COGL_FLAGS_FOREACH_END;
}
else
{
unsigned long mask = _cogl_bitmask_to_bits (bitmask);
- int bit = 0;
+ int bit_num;
- while (mask)
+ COGL_FLAGS_FOREACH_START (&mask, 1, bit_num)
{
- int next_bit = _cogl_util_ffsl (mask);
-
- bit += next_bit;
- mask >>= next_bit;
-
- if (!func (bit - 1, user_data))
+ if (!func (bit_num, user_data))
return;
}
+ COGL_FLAGS_FOREACH_END;
}
}
diff --git a/cogl/cogl-flags.h b/cogl/cogl-flags.h
index 14fb8f19..bf5eadd4 100644
--- a/cogl/cogl-flags.h
+++ b/cogl/cogl-flags.h
@@ -29,6 +29,8 @@
#include <glib.h>
+#include "cogl-util.h"
+
G_BEGIN_DECLS
/* These are macros used to implement a fixed-size array of bits. This
@@ -78,6 +80,40 @@ G_BEGIN_DECLS
~COGL_FLAGS_GET_MASK (flag)); \
} G_STMT_END
+/* Macros to help iterate an array of flags. It should be used like
+ * this:
+ *
+ * int n_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (...);
+ * unsigned long flags[n_longs];
+ * int bit_num;
+ *
+ * COGL_FLAGS_FOREACH_START (flags, n_longs, bit_num)
+ * {
+ * do_something_with_the_bit (bit_num);
+ * }
+ * COGL_FLAGS_FOREACH_END;
+ */
+#define COGL_FLAGS_FOREACH_START(array, n_longs, bit) \
+ G_STMT_START { \
+ const unsigned long *_p = (array); \
+ int _n_longs = (n_longs); \
+ int _i; \
+ \
+ for (_i = 0; _i < _n_longs; _i++) \
+ { \
+ unsigned long _mask = *(_p++); \
+ \
+ (bit) = _i * sizeof (unsigned long) * 8 - 1; \
+ \
+ while (_mask) \
+ { \
+ int _next_bit = _cogl_util_ffsl (_mask); \
+ (bit) += _next_bit; \
+ _mask >>= _next_bit;
+
+#define COGL_FLAGS_FOREACH_END \
+ } } } G_STMT_END
+
G_END_DECLS
#endif /* __COGL_FLAGS_H */