[cogl/wip/neil/pipeline-uniforms: 7/18] cogl-flags: Add some macros to help iterate the bits



commit 43296eb1a1c3cbaecff95b56dde5b7a23556ef4c
Author: Neil Roberts <neil linux intel com>
Date:   Wed Nov 2 13:41:32 2011 +0000

    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.

 cogl/cogl-bitmask.c |   36 +++++++++++-------------------------
 cogl/cogl-flags.h   |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 25 deletions(-)
---
diff --git a/cogl/cogl-bitmask.c b/cogl/cogl-bitmask.c
index 1fe2198..ec69625 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 14fb8f1..bf5eadd 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 */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]