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>
This commit is contained in:
Neil Roberts 2011-11-02 13:41:32 +00:00
parent dbc31b70cc
commit d706991579
3 changed files with 48 additions and 25 deletions

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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 */