#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. */
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)
{
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 ();
}
};
((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 */