From d70699157979cf19a5598f27fd071a8fd05f2840 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 2 Nov 2011 13:41:32 +0000 Subject: [PATCH] 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 --- cogl-pango/Makefile.am | 1 + cogl/cogl-bitmask.c | 36 +++++++++++------------------------- cogl/cogl-flags.h | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/cogl-pango/Makefile.am b/cogl-pango/Makefile.am index 6917c1cd4..5ee1fabb1 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 1fe21983b..ec69625db 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 14fb8f198..bf5eadd4f 100644 --- a/cogl/cogl-flags.h +++ b/cogl/cogl-flags.h @@ -29,6 +29,8 @@ #include +#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 */