Move hb_vector_t and hb_lockable_set_t to hb-dsalgs.hh

This commit is contained in:
Behdad Esfahbod 2018-07-10 14:05:00 +02:00
parent 9e53b08329
commit d652ef299d
2 changed files with 311 additions and 315 deletions

View File

@ -209,4 +209,315 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
}
#define HB_VECTOR_INIT {0, 0, false, nullptr}
template <typename Type, unsigned int StaticSize=8>
struct hb_vector_t
{
unsigned int len;
unsigned int allocated;
bool successful;
Type *arrayZ;
Type static_array[StaticSize];
void init (void)
{
len = 0;
allocated = ARRAY_LENGTH (static_array);
successful = true;
arrayZ = static_array;
}
inline Type& operator [] (unsigned int i)
{
if (unlikely (i >= len))
return Crap (Type);
return arrayZ[i];
}
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len))
return Null(Type);
return arrayZ[i];
}
inline Type *push (void)
{
if (unlikely (!resize (len + 1)))
return &Crap(Type);
return &arrayZ[len - 1];
}
inline Type *push (const Type& v)
{
Type *p = push ();
*p = v;
return p;
}
/* Allocate for size but don't adjust len. */
inline bool alloc (unsigned int size)
{
if (unlikely (!successful))
return false;
if (likely (size <= allocated))
return true;
/* Reallocate */
unsigned int new_allocated = allocated;
while (size >= new_allocated)
new_allocated += (new_allocated >> 1) + 8;
Type *new_array = nullptr;
if (arrayZ == static_array)
{
new_array = (Type *) calloc (new_allocated, sizeof (Type));
if (new_array)
memcpy (new_array, arrayZ, len * sizeof (Type));
}
else
{
bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows))
new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
}
if (unlikely (!new_array))
{
successful = false;
return false;
}
arrayZ = new_array;
allocated = new_allocated;
return true;
}
inline bool resize (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (!alloc (size))
return false;
if (size > len)
memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
len = size;
return true;
}
inline void pop (void)
{
if (!len) return;
len--;
}
inline void remove (unsigned int i)
{
if (unlikely (i >= len))
return;
memmove (static_cast<void *> (&arrayZ[i]),
static_cast<void *> (&arrayZ[i + 1]),
(len - i - 1) * sizeof (Type));
len--;
}
inline void shrink (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size < len)
len = size;
}
template <typename T>
inline Type *find (T v) {
for (unsigned int i = 0; i < len; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline const Type *find (T v) const {
for (unsigned int i = 0; i < len; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
inline void qsort (int (*cmp)(const void*, const void*))
{
::qsort (arrayZ, len, sizeof (Type), cmp);
}
inline void qsort (void)
{
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
inline void qsort (unsigned int start, unsigned int end)
{
::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
}
template <typename T>
inline Type *lsearch (const T &x)
{
for (unsigned int i = 0; i < len; i++)
if (0 == this->arrayZ[i].cmp (&x))
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline Type *bsearch (const T &x)
{
unsigned int i;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline const Type *bsearch (const T &x) const
{
unsigned int i;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline bool bfind (const T &x, unsigned int *i) const
{
int min = 0, max = (int) this->len - 1;
while (min <= max)
{
int mid = (min + max) / 2;
int c = this->arrayZ[mid].cmp (&x);
if (c < 0)
max = mid - 1;
else if (c > 0)
min = mid + 1;
else
{
*i = mid;
return true;
}
}
if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
max++;
*i = max;
return false;
}
inline void fini (void)
{
if (arrayZ != static_array)
free (arrayZ);
arrayZ = nullptr;
allocated = len = 0;
}
};
template <typename Type>
struct hb_auto_t : Type
{
hb_auto_t (void) { Type::init (); }
~hb_auto_t (void) { Type::fini (); }
private: /* Hide */
void init (void) {}
void fini (void) {}
};
template <typename Type>
struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {};
#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
template <typename item_t, typename lock_t>
struct hb_lockable_set_t
{
hb_vector_t <item_t, 1> items;
inline void init (void) { items.init (); }
template <typename T>
inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
{
l.lock ();
item_t *item = items.find (v);
if (item) {
if (replace) {
item_t old = *item;
*item = v;
l.unlock ();
old.fini ();
}
else {
item = nullptr;
l.unlock ();
}
} else {
item = items.push (v);
l.unlock ();
}
return item;
}
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.fini ();
} else {
l.unlock ();
}
}
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 *find_or_insert (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (!item) {
item = items.push (v);
}
l.unlock ();
return item;
}
inline void fini (lock_t &l)
{
if (!items.len) {
/* No need for locking. */
items.fini ();
return;
}
l.lock ();
while (items.len) {
item_t old = items[items.len - 1];
items.pop ();
l.unlock ();
old.fini ();
l.lock ();
}
items.fini ();
l.unlock ();
}
};
#endif /* HB_DSALGS_HH */

View File

@ -652,321 +652,6 @@ struct CrapOrNull<const Type> {
#define CrapOrNull(Type) CrapOrNull<Type>::get ()
/* arrays and maps */
#define HB_VECTOR_INIT {0, 0, false, nullptr}
template <typename Type, unsigned int StaticSize=8>
struct hb_vector_t
{
unsigned int len;
unsigned int allocated;
bool successful;
Type *arrayZ;
Type static_array[StaticSize];
void init (void)
{
len = 0;
allocated = ARRAY_LENGTH (static_array);
successful = true;
arrayZ = static_array;
}
inline Type& operator [] (unsigned int i)
{
if (unlikely (i >= len))
return Crap (Type);
return arrayZ[i];
}
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= len))
return Null(Type);
return arrayZ[i];
}
inline Type *push (void)
{
if (unlikely (!resize (len + 1)))
return &Crap(Type);
return &arrayZ[len - 1];
}
inline Type *push (const Type& v)
{
Type *p = push ();
*p = v;
return p;
}
/* Allocate for size but don't adjust len. */
inline bool alloc (unsigned int size)
{
if (unlikely (!successful))
return false;
if (likely (size <= allocated))
return true;
/* Reallocate */
unsigned int new_allocated = allocated;
while (size >= new_allocated)
new_allocated += (new_allocated >> 1) + 8;
Type *new_array = nullptr;
if (arrayZ == static_array)
{
new_array = (Type *) calloc (new_allocated, sizeof (Type));
if (new_array)
memcpy (new_array, arrayZ, len * sizeof (Type));
}
else
{
bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
if (likely (!overflows))
new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
}
if (unlikely (!new_array))
{
successful = false;
return false;
}
arrayZ = new_array;
allocated = new_allocated;
return true;
}
inline bool resize (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (!alloc (size))
return false;
if (size > len)
memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
len = size;
return true;
}
inline void pop (void)
{
if (!len) return;
len--;
}
inline void remove (unsigned int i)
{
if (unlikely (i >= len))
return;
memmove (static_cast<void *> (&arrayZ[i]),
static_cast<void *> (&arrayZ[i + 1]),
(len - i - 1) * sizeof (Type));
len--;
}
inline void shrink (int size_)
{
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size < len)
len = size;
}
template <typename T>
inline Type *find (T v) {
for (unsigned int i = 0; i < len; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline const Type *find (T v) const {
for (unsigned int i = 0; i < len; i++)
if (arrayZ[i] == v)
return &arrayZ[i];
return nullptr;
}
inline void qsort (int (*cmp)(const void*, const void*))
{
::qsort (arrayZ, len, sizeof (Type), cmp);
}
inline void qsort (void)
{
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
inline void qsort (unsigned int start, unsigned int end)
{
::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
}
template <typename T>
inline Type *lsearch (const T &x)
{
for (unsigned int i = 0; i < len; i++)
if (0 == this->arrayZ[i].cmp (&x))
return &arrayZ[i];
return nullptr;
}
template <typename T>
inline Type *bsearch (const T &x)
{
unsigned int i;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline const Type *bsearch (const T &x) const
{
unsigned int i;
return bfind (x, &i) ? &arrayZ[i] : nullptr;
}
template <typename T>
inline bool bfind (const T &x, unsigned int *i) const
{
int min = 0, max = (int) this->len - 1;
while (min <= max)
{
int mid = (min + max) / 2;
int c = this->arrayZ[mid].cmp (&x);
if (c < 0)
max = mid - 1;
else if (c > 0)
min = mid + 1;
else
{
*i = mid;
return true;
}
}
if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
max++;
*i = max;
return false;
}
inline void fini (void)
{
if (arrayZ != static_array)
free (arrayZ);
arrayZ = nullptr;
allocated = len = 0;
}
};
template <typename Type>
struct hb_auto_t : Type
{
hb_auto_t (void) { Type::init (); }
~hb_auto_t (void) { Type::fini (); }
private: /* Hide */
void init (void) {}
void fini (void) {}
};
template <typename Type>
struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {};
#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
template <typename item_t, typename lock_t>
struct hb_lockable_set_t
{
hb_vector_t <item_t, 1> items;
inline void init (void) { items.init (); }
template <typename T>
inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
{
l.lock ();
item_t *item = items.find (v);
if (item) {
if (replace) {
item_t old = *item;
*item = v;
l.unlock ();
old.fini ();
}
else {
item = nullptr;
l.unlock ();
}
} else {
item = items.push (v);
l.unlock ();
}
return item;
}
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.fini ();
} else {
l.unlock ();
}
}
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 *find_or_insert (T v, lock_t &l)
{
l.lock ();
item_t *item = items.find (v);
if (!item) {
item = items.push (v);
}
l.unlock ();
return item;
}
inline void fini (lock_t &l)
{
if (!items.len) {
/* No need for locking. */
items.fini ();
return;
}
l.lock ();
while (items.len) {
item_t old = items[items.len - 1];
items.pop ();
l.unlock ();
old.fini ();
l.lock ();
}
items.fini ();
l.unlock ();
}
};
/* ASCII tag/character handling */
static inline bool ISALPHA (unsigned char c)