Use variadic macros for debugging
[framework/uifw/harfbuzz.git] / src / hb-private.hh
index 28c33b7..f7731df 100644 (file)
@@ -85,6 +85,7 @@ HB_BEGIN_DECLS
 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
 
 #define ASSERT_STATIC_EXPR(_cond) ((void) sizeof (char[(_cond) ? 1 : -1]))
+#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
 
 
 /* Lets assert int types.  Saves trouble down the road. */
@@ -228,17 +229,15 @@ HB_END_DECLS
 
 
 template <typename Type, unsigned int StaticSize>
-struct hb_static_array_t {
+struct hb_prealloced_array_t {
 
   unsigned int len;
   unsigned int allocated;
   Type *array;
   Type static_array[StaticSize];
 
-  inline Type& operator [] (unsigned int i)
-  {
-    return array[i];
-  }
+  inline Type& operator [] (unsigned int i) { return array[i]; }
+  inline const Type& operator [] (unsigned int i) const { return array[i]; }
 
   inline Type *push (void)
   {
@@ -277,62 +276,140 @@ struct hb_static_array_t {
     len--;
     /* TODO: shrink array if needed */
   }
-};
 
-template <typename Type>
-struct hb_array_t : hb_static_array_t<Type, 2> {};
+  inline void shrink (unsigned int l)
+  {
+     if (l < len)
+       len = l;
+    /* TODO: shrink array if needed */
+  }
 
+  template <typename T>
+  inline Type *find (T v) {
+    for (unsigned int i = 0; i < len; i++)
+      if (array[i] == v)
+       return &array[i];
+    return NULL;
+  }
+  template <typename T>
+  inline const Type *find (T v) const {
+    for (unsigned int i = 0; i < len; i++)
+      if (array[i] == v)
+       return &array[i];
+    return NULL;
+  }
 
-template <typename item_t>
-struct hb_set_t
-{
-  hb_array_t <item_t> items;
+  inline void sort (void)
+  {
+    qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
 
-  private:
+  inline void sort (unsigned int start, unsigned int end)
+  {
+    qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
 
   template <typename T>
-  inline item_t *find (T v) {
-    for (unsigned int i = 0; i < items.len; i++)
-      if (items[i] == v)
-       return &items[i];
-    return NULL;
+  inline Type *bsearch (T *key)
+  {
+    return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
+  template <typename T>
+  inline const Type *bsearch (T *key) const
+  {
+    return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
   }
 
-  public:
+  inline void finish (void)
+  {
+    if (array != static_array)
+      free (array);
+    array = NULL;
+    allocated = len = 0;
+  }
+};
+
+template <typename Type>
+struct hb_array_t : hb_prealloced_array_t<Type, 2> {};
+
+
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+  hb_array_t <item_t> items;
 
   template <typename T>
-  inline bool insert (T v)
+  inline item_t *replace_or_insert (T v, lock_t &l)
   {
-    item_t *item = find (v);
-    if (item)
-      item->finish ();
-    else
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      item_t old = *item;
+      *item = v;
+      l.unlock ();
+      old.finish ();
+    } else {
       item = items.push ();
-    if (unlikely (!item)) return false;
-    *item = v;
-    return true;
+      if (likely (item))
+       *item = v;
+      l.unlock ();
+    }
+    return item;
   }
 
   template <typename T>
-  inline void remove (T v)
+  inline void remove (T v, lock_t &l)
   {
-    item_t *item = find (v);
-    if (!item) return;
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      item_t old = *item;
+      *item = items[items.len - 1];
+      items.pop ();
+      l.unlock ();
+      old.finish ();
+    } else {
+      l.unlock ();
+    }
+  }
 
-    item->finish ();
-    *item = items[items.len - 1];
-    items.pop ();
+  template <typename T>
+  inline bool find (T v, item_t *i, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+      *i = *item;
+    l.unlock ();
+    return !!item;
   }
 
   template <typename T>
-  inline item_t *get (T v)
+  inline item_t *find_or_insert (T v, lock_t &l)
   {
-    return find (v);
+    l.lock ();
+    item_t *item = items.find (v);
+    if (!item) {
+      item = items.push ();
+      if (likely (item))
+        *item = v;
+    }
+    l.unlock ();
+    return item;
   }
 
-  void finish (void) {
-    for (unsigned i = 0; i < items.len; i++)
-      items[i].finish ();
+  inline void finish (lock_t &l)
+  {
+    l.lock ();
+    while (items.len) {
+      item_t old = items[items.len - 1];
+       items.pop ();
+       l.unlock ();
+       old.finish ();
+       l.lock ();
+    }
+    items.finish ();
+    l.unlock ();
   }
 
 };
@@ -375,24 +452,57 @@ static inline unsigned char TOLOWER (unsigned char c)
                                  ((const char *) s)[3]))
 
 
+/* C++ helpers */
+
+/* Makes class uncopyable.  Use in private: section. */
+#define NO_COPY(T) \
+  T (const T &o); \
+  T &operator = (const T &o)
+
+
 /* Debug */
 
 #ifndef HB_DEBUG
 #define HB_DEBUG 0
 #endif
 
+#define DEBUG_LEVEL(WHAT, LEVEL) (HB_DEBUG_##WHAT && (int) (LEVEL) < (int) (HB_DEBUG_##WHAT))
+#define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0))
+
+#define DEBUG_MSG_LEVEL(WHAT, LEVEL, ...) (void) (DEBUG_LEVEL (WHAT, LEVEL)  && fprintf (stderr, __VA_ARGS__))
+#define DEBUG_MSG(WHAT, ...) DEBUG_MSG_LEVEL (WHAT, 0, __VA_ARGS__)
+
 static inline bool /* always returns TRUE */
 _hb_trace (const char *what,
-          const char *function,
+          const char *message,
           const void *obj,
           unsigned int depth,
           unsigned int max_depth)
 {
-  (void) ((depth < max_depth) && fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, depth, depth, function));
+  (void) ((depth < max_depth) && fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, depth, depth, message));
   return TRUE;
 }
 
 
+/* Pre-mature optimization:
+ * Checks for lo <= u <= hi but with an optimization if lo and hi
+ * are only different in a contiguous set of lower-most bits.
+ */
+static inline bool
+hb_codepoint_in_range (hb_codepoint_t u, hb_codepoint_t lo, hb_codepoint_t hi)
+{
+  if ( ((lo^hi) & lo) == 0 &&
+       ((lo^hi) & hi) == (lo^hi) &&
+       ((lo^hi) & ((lo^hi) + 1)) == 0 )
+    return (u & ~(lo^hi)) == lo;
+  else
+    return lo <= u && u <= hi;
+}
+
+
+/* Useful for set-operations on small enums */
+#define FLAG(x) (1<<(x))
+
 HB_END_DECLS
 
 #endif /* HB_PRIVATE_HH */