[Indic] For old-style Indic tables, move Halant around
[framework/uifw/harfbuzz.git] / src / hb-private.hh
index cac434a..23fc0af 100644 (file)
@@ -36,6 +36,7 @@
 #include "hb-common.h"
 
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <assert.h>
 
@@ -45,6 +46,7 @@
  * someway around that. */
 #include <stdio.h>
 #include <errno.h>
+#include <stdarg.h>
 
 HB_BEGIN_DECLS
 
@@ -85,6 +87,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. */
@@ -123,9 +126,11 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
 #if __GNUC__ >= 3
 #define HB_PURE_FUNC   __attribute__((pure))
 #define HB_CONST_FUNC  __attribute__((const))
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
 #else
 #define HB_PURE_FUNC
 #define HB_CONST_FUNC
+#define HB_PRINTF_FUCN(format_idx, arg_idx)
 #endif
 #if __GNUC__ >= 4
 #define HB_UNUSED      __attribute__((unused))
@@ -221,72 +226,6 @@ _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
 typedef int (*hb_compare_func_t) (const void *, const void *);
 
 
-/* We need external help for these */
-
-#ifdef HAVE_GLIB
-
-#include <glib.h>
-
-typedef volatile int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)     g_atomic_int_exchange_and_add (&(AI), V)
-#define hb_atomic_int_get(AI)                  g_atomic_int_get (&(AI))
-#define hb_atomic_int_set(AI, V)               g_atomic_int_set (&(AI), V)
-
-typedef GStaticMutex hb_mutex_t;
-#define HB_MUTEX_INIT                  G_STATIC_MUTEX_INIT
-#define hb_mutex_init(M)               g_static_mutex_init (&(M))
-#define hb_mutex_lock(M)               g_static_mutex_lock (&(M))
-#define hb_mutex_trylock(M)            g_static_mutex_trylock (&(M))
-#define hb_mutex_unlock(M)             g_static_mutex_unlock (&(M))
-#define hb_mutex_free(M)               g_static_mutex_free (&(M))
-
-#else
-
-#ifdef _MSC_VER
-
-#include <intrin.h>
-
-typedef long hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)     _InterlockedExchangeAdd (&(AI), V)
-#define hb_atomic_int_get(AI)                  (_ReadBarrier (), (AI))
-#define hb_atomic_int_set(AI, V)               ((void) _InterlockedExchange (&(AI), (V)))
-
-typedef void * hb_mutex_t;
-extern HB_INTERNAL hb_mutex_t _hb_win32_mutex_create (void);
-extern HB_INTERNAL void _hb_win32_mutex_init (hb_mutex_t *m);
-extern HB_INTERNAL void _hb_win32_mutex_lock (hb_mutex_t m);
-extern HB_INTERNAL int _hb_win32_mutex_trylock (hb_mutex_t m);
-extern HB_INTERNAL void _hb_win32_mutex_unlock (hb_mutex_t m);
-extern HB_INTERNAL void _hb_win32_mutex_free (hb_mutex_t *m);
-#define HB_MUTEX_INIT                          _hb_win32_mutex_create ()
-#define hb_mutex_init(M)                       _hb_win32_mutex_init (&(M))
-#define hb_mutex_lock(M)                       _hb_win32_mutex_lock ((M))
-#define hb_mutex_trylock(M)                    _hb_win32_mutex_trylock ((M))
-#define hb_mutex_unlock(M)                     _hb_win32_mutex_unlock ((M))
-#define hb_mutex_free(M)                       _hb_win32_mutex_free (&(M))
-
-#else
-
-#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
-
-typedef volatile int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)     ((AI) += (V), (AI) - (V))
-#define hb_atomic_int_get(AI)                  (AI)
-#define hb_atomic_int_set(AI, V)               ((void) ((AI) = (V)))
-
-typedef volatile int hb_mutex_t;
-#define HB_MUTEX_INIT                          0
-#define hb_mutex_init(M)                       ((void) ((M) = 0))
-#define hb_mutex_lock(M)                       ((void) ((M) = 1))
-#define hb_mutex_trylock(M)                    ((M) = 1, 1)
-#define hb_mutex_unlock(M)                     ((void) ((M) = 0))
-#define hb_mutex_free(M)                       ((void) ((M) = 2))
-
-#endif
-
-#endif
-
-
 HB_END_DECLS
 
 
@@ -294,19 +233,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];
 
-  void finish (void) { for (unsigned i = 0; i < len; i++) array[i].finish (); }
-
-  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)
   {
@@ -345,71 +280,142 @@ struct hb_static_array_t {
     len--;
     /* TODO: shrink array if needed */
   }
+
+  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;
+  }
+
+  inline void sort (void)
+  {
+    qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+  }
+
+  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 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);
+  }
+
+  inline void finish (void)
+  {
+    if (array != static_array)
+      free (array);
+    array = NULL;
+    allocated = len = 0;
+  }
 };
 
 template <typename Type>
-struct hb_array_t : hb_static_array_t<Type, 2> {};
+struct hb_array_t : hb_prealloced_array_t<Type, 2> {};
 
 
-template <typename Key, typename Value>
-struct hb_map_t
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
 {
-  struct item_t {
-    Key key;
-    /* unsigned int hash; */
-    Value value;
-
-    void finish (void) { value.finish (); }
-  };
-
   hb_array_t <item_t> items;
 
-  private:
-
-  inline item_t *find (Key key) {
-    if (unlikely (!key)) return NULL;
-    for (unsigned int i = 0; i < items.len; i++)
-      if (key == items[i].key)
-       return &items[i];
-    return NULL;
+  template <typename T>
+  inline item_t *replace_or_insert (T v, lock_t &l)
+  {
+    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 (likely (item))
+       *item = v;
+      l.unlock ();
+    }
+    return item;
   }
 
-  public:
+  template <typename T>
+  inline void remove (T v, lock_t &l)
+  {
+    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 ();
+    }
+  }
 
-  inline bool set (Key   key,
-                  Value &value)
+  template <typename T>
+  inline bool find (T v, item_t *i, lock_t &l)
   {
-    if (unlikely (!key)) return NULL;
-    item_t *item;
-    item = find (key);
+    l.lock ();
+    item_t *item = items.find (v);
     if (item)
-      item->finish ();
-    else
-      item = items.push ();
-    if (unlikely (!item)) return false;
-    item->key = key;
-    item->value = value;
-    return true;
+      *i = *item;
+    l.unlock ();
+    return !!item;
   }
 
-  inline void unset (Key &key)
+  template <typename T>
+  inline item_t *find_or_insert (T v, lock_t &l)
   {
-    item_t *item;
-    item = find (key);
-    if (!item) return;
-
-    item->finish ();
-    *item = items[items.len - 1];
-    items.pop ();
+    l.lock ();
+    item_t *item = items.find (v);
+    if (!item) {
+      item = items.push ();
+      if (likely (item))
+        *item = v;
+    }
+    l.unlock ();
+    return item;
   }
 
-  inline Value *get (Key key)
+  inline void finish (lock_t &l)
   {
-    item_t *item = find (key);
-    return item ? &item->value : NULL;
+    l.lock ();
+    while (items.len) {
+      item_t old = items[items.len - 1];
+       items.pop ();
+       l.unlock ();
+       old.finish ();
+       l.lock ();
+    }
+    items.finish ();
+    l.unlock ();
   }
 
-  void finish (void) { items.finish (); }
 };
 
 
@@ -450,23 +456,170 @@ 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 */
 
+HB_END_DECLS
+
 #ifndef HB_DEBUG
 #define HB_DEBUG 0
 #endif
 
-static inline bool /* always returns TRUE */
-_hb_trace (const char *what,
-          const char *function,
-          const void *obj,
-          unsigned int depth,
-          unsigned int max_depth)
+static inline bool
+_hb_debug (unsigned int level,
+          unsigned int max_level)
+{
+  return level < max_level;
+}
+
+#define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
+#define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0))
+
+template <int max_level> inline bool /* always returns TRUE */
+_hb_debug_msg (const char *what,
+              const void *obj,
+              const char *func,
+              bool indented,
+              int level,
+              const char *message,
+              ...) HB_PRINTF_FUNC(6, 7);
+template <int max_level> inline bool /* always returns TRUE */
+_hb_debug_msg (const char *what,
+              const void *obj,
+              const char *func,
+              bool indented,
+              int level,
+              const char *message,
+              ...)
+{
+  va_list ap;
+  va_start (ap, message);
+
+  (void) (_hb_debug (level, max_level) &&
+         fprintf (stderr, "%s(%p): ", what, obj) &&
+         (func && fprintf (stderr, "%s: ", func), TRUE) &&
+         (indented && fprintf (stderr, "%-*d-> ", level + 1, level), TRUE) &&
+         vfprintf (stderr, message, ap) &&
+         fprintf (stderr, "\n"));
+
+  va_end (ap);
+
+  return TRUE;
+}
+template <> inline bool /* always returns TRUE */
+_hb_debug_msg<0> (const char *what,
+                 const void *obj,
+                 const char *func,
+                 bool indented,
+                 int level,
+                 const char *message,
+                 ...) HB_PRINTF_FUNC(6, 7);
+template <> inline bool /* always returns TRUE */
+_hb_debug_msg<0> (const char *what,
+                 const void *obj,
+                 const char *func,
+                 bool indented,
+                 int level,
+                 const char *message,
+                 ...)
 {
-  (void) ((depth < max_depth) && fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, depth, depth, function));
   return TRUE;
 }
 
+#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, FALSE, (LEVEL), __VA_ARGS__)
+#define DEBUG_MSG(WHAT, OBJ, ...) DEBUG_MSG_LEVEL (WHAT, OBJ, 0, __VA_ARGS__)
+#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, __VA_ARGS__)
+
+
+/*
+ * Trace
+ */
+
+template <int max_level>
+struct hb_auto_trace_t {
+  explicit inline hb_auto_trace_t (unsigned int *plevel_,
+                                  const char *what,
+                                  const void *obj,
+                                  const char *func,
+                                  const char *message) : plevel(plevel_)
+  {
+    if (max_level) ++*plevel;
+    /* TODO support variadic args here */
+    _hb_debug_msg<max_level> (what, obj, func, TRUE, *plevel, "%s", message);
+  }
+  ~hb_auto_trace_t (void) { if (max_level) --*plevel; }
+
+  private:
+  unsigned int *plevel;
+};
+template <> /* Optimize when tracing is disabled */
+struct hb_auto_trace_t<0> {
+  explicit inline hb_auto_trace_t (unsigned int *plevel_,
+                                  const char *what,
+                                  const void *obj,
+                                  const char *func,
+                                  const char *message) {}
+};
+
+
+/* Misc */
+
+
+/* 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.
+ */
+template <typename T> inline bool
+hb_in_range (T u, T lo, 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.
+ * For example, for testing "x ∈ {x1, x2, x3}" use:
+ * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
+ */
+#define FLAG(x) (1<<(x))
+
+
+template <typename T> inline void
+hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
+{
+  if (unlikely (!len))
+    return;
+
+  unsigned int k = len - 1;
+  do {
+    unsigned int new_k = 0;
+
+    for (unsigned int j = 0; j < k; j++)
+      if (compar (&array[j], &array[j+1]) > 0) {
+        T t;
+       t = array[j];
+       array[j] = array[j + 1];
+       array[j + 1] = t;
+
+       new_k = j;
+      }
+    k = new_k;
+  } while (k);
+}
+
+
+HB_BEGIN_DECLS
 
 HB_END_DECLS