Add set iterator
authorBehdad Esfahbod <behdad@behdad.org>
Fri, 25 May 2012 18:17:54 +0000 (14:17 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Fri, 25 May 2012 18:17:54 +0000 (14:17 -0400)
src/hb-set-private.hh
src/hb-set.cc
src/hb-set.h
util/hb-ot-shape-closure.cc

index df96b99..9d8ba4a 100644 (file)
@@ -32,6 +32,7 @@
 #include "hb-object-private.hh"
 
 
+/* TODO Make this faster and memmory efficient. */
 
 struct _hb_set_t
 {
@@ -51,6 +52,7 @@ struct _hb_set_t
   }
   inline void add (hb_codepoint_t g)
   {
+    if (unlikely (g == SENTINEL)) return;
     if (unlikely (g > MAX_G)) return;
     elt (g) |= mask (g);
   }
@@ -107,6 +109,23 @@ struct _hb_set_t
     for (unsigned int i = 0; i < ELTS; i++)
       elts[i] ^= other->elts[i];
   }
+  inline bool next (hb_codepoint_t *codepoint)
+  {
+    if (unlikely (*codepoint == SENTINEL)) {
+      hb_codepoint_t i = get_min ();
+      if (i != SENTINEL) {
+        *codepoint = i;
+       return true;
+      } else
+        return false;
+    }
+    for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++)
+      if (has (i)) {
+        *codepoint = i;
+       return true;
+      }
+    return false;
+  }
   inline hb_codepoint_t get_min (void) const
   {
     for (unsigned int i = 0; i < ELTS; i++)
@@ -114,7 +133,7 @@ struct _hb_set_t
        for (unsigned int j = 0; i < BITS; j++)
          if (elts[i] & (1 << j))
            return i * BITS + j;
-    return 0;
+    return SENTINEL;
   }
   inline hb_codepoint_t get_max (void) const
   {
@@ -123,15 +142,16 @@ struct _hb_set_t
        for (unsigned int j = BITS; j; j--)
          if (elts[i - 1] & (1 << (j - 1)))
            return (i - 1) * BITS + (j - 1);
-    return 0;
+    return SENTINEL;
   }
 
   typedef uint32_t elt_t;
-  static const unsigned int MAX_G = 65536 - 1;
+  static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */
   static const unsigned int SHIFT = 5;
   static const unsigned int BITS = (1 << SHIFT);
   static const unsigned int MASK = BITS - 1;
   static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
+  static  const hb_codepoint_t SENTINEL = (hb_codepoint_t) -1;
 
   elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
   elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
index 7103bcd..5045386 100644 (file)
@@ -182,3 +182,10 @@ hb_set_max (hb_set_t *set)
 {
   return set->get_max ();
 }
+
+hb_bool_t
+hb_set_next (hb_set_t       *set,
+            hb_codepoint_t *codepoint)
+{
+  return set->next (codepoint);
+}
index 38bb84b..97e68e4 100644 (file)
@@ -77,6 +77,8 @@ hb_bool_t
 hb_set_has (hb_set_t       *set,
            hb_codepoint_t  codepoint);
 
+/* Right now limited to 16-bit integers.  Eventually will do full codepoint range, sans -1
+ * which we will use as a sentinel. */
 void
 hb_set_add (hb_set_t       *set,
            hb_codepoint_t  codepoint);
@@ -109,14 +111,19 @@ void
 hb_set_symmetric_difference (hb_set_t *set,
                             hb_set_t *other);
 
-/* Undefined if set empty */
+/* Returns -1 if set empty. */
 hb_codepoint_t
 hb_set_min (hb_set_t *set);
 
-/* Undefined if set empty */
+/* Returns -1 if set empty. */
 hb_codepoint_t
 hb_set_max (hb_set_t *set);
 
+/* Pass -1 in to get started. */
+hb_bool_t
+hb_set_next (hb_set_t       *set,
+            hb_codepoint_t *codepoint);
+
 /* TODO: Add faster iteration API? */
 
 
index afd88ae..55481c6 100644 (file)
@@ -66,11 +66,13 @@ struct shape_closure_consumer_t : option_group_t
 
     hb_set_clear (glyphs);
     shaper.shape_closure (text, text_len, font, buffer, glyphs);
+
+    if (hb_set_empty (glyphs))
+      return;
+
     /* Print it out! */
-    hb_codepoint_t start = hb_set_min (glyphs);
-    hb_codepoint_t end = 1 + hb_set_max (glyphs);
     bool first = true;
-    for (hb_codepoint_t i = start; i < end; i++)
+    for (hb_codepoint_t i = -1; hb_set_next (glyphs, &i);)
       if (hb_set_has (glyphs, i)) {
         if (first)
          first = false;