diff --git a/src/hb-vector.hh b/src/hb-vector.hh index bb7af2b82..46efb9705 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -342,24 +342,39 @@ struct hb_vector_t if (unlikely (in_error ())) return false; - if (likely (size <= (unsigned) allocated)) - return true; + unsigned int new_allocated; + if (exact) + { + /* If exact was specified, we allow shrinking the storage. */ + size = hb_max (size, length); + if (size <= (unsigned) allocated && + size >= (unsigned) allocated >> 2) + return true; - /* Reallocate */ + new_allocated = size; + } + else + { + if (likely (size <= (unsigned) allocated)) + return true; + + new_allocated = allocated; + while (size > new_allocated) + new_allocated += (new_allocated >> 1) + 8; + } - unsigned int new_allocated = exact ? size : allocated; - while (size > new_allocated) - new_allocated += (new_allocated >> 1) + 8; + + /* Reallocate */ Type *new_array = nullptr; bool overflows = (int) in_error () || - (new_allocated < (unsigned) allocated) || + (new_allocated < size) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); if (likely (!overflows)) new_array = realloc_vector (new_allocated); - if (unlikely (!new_array)) + if (unlikely (new_allocated && !new_array)) { allocated = -1; return false; @@ -429,6 +444,8 @@ struct hb_vector_t return; shrink_vector (size); + + alloc (size, true); /* To force shrinking memory if needed. */ }