mirror of
https://github.com/brl/mutter.git
synced 2025-01-23 09:59:03 +00:00
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:
parent
dbc31b70cc
commit
d706991579
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user