diff options
Diffstat (limited to 'src/hb-array.hh')
-rw-r--r-- | src/hb-array.hh | 94 |
1 files changed, 24 insertions, 70 deletions
diff --git a/src/hb-array.hh b/src/hb-array.hh index 17562bc33..5884007c1 100644 --- a/src/hb-array.hh +++ b/src/hb-array.hh @@ -100,18 +100,10 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> /* Ouch. The operator== compares the contents of the array. For range-based for loops, * it's best if we can just compare arrayZ, though comparing contents is still fast, * but also would require that Type has operator==. As such, we optimize this operator - * for range-based for loop and just compare arrayZ and length. - * - * The above comment is outdated now because we implemented separate begin/end to - * objects that were using hb_array_t for range-based loop before. */ + * for range-based for loop and just compare arrayZ and length. */ bool operator != (const hb_array_t& o) const { return this->arrayZ != o.arrayZ || this->length != o.length; } - /* Faster range-based for loop without bounds-check. */ - Type *begin () const { return arrayZ; } - Type *end () const { return arrayZ + length; } - - /* Extra operators. */ Type * operator & () const { return arrayZ; } @@ -120,11 +112,11 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> HB_INTERNAL bool operator == (const hb_array_t &o) const; - uint32_t hash () const - { + uint32_t hash () const { uint32_t current = 0; - for (auto &v : *this) - current = current * 31 + hb_hash (v); + for (unsigned int i = 0; i < this->length; i++) { + current = current * 31 + hb_hash (this->arrayZ[i]); + } return current; } @@ -192,18 +184,23 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*)) { - //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), ""); if (likely (length)) hb_qsort (arrayZ, length, this->get_item_size (), cmp_); return hb_sorted_array_t<Type> (*this); } hb_sorted_array_t<Type> qsort () { - //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), ""); if (likely (length)) hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp); return hb_sorted_array_t<Type> (*this); } + void qsort (unsigned int start, unsigned int end) + { + end = hb_min (end, length); + assert (start <= end); + if (likely (start < end)) + hb_qsort (arrayZ + start, end - start, this->get_item_size (), Type::cmp); + } /* * Other methods. @@ -265,31 +262,17 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> void fini () { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; } - template <typename hb_serialize_context_t, - typename U = Type, - hb_enable_if (!(sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>)))> + template <typename hb_serialize_context_t> hb_array_t copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); auto* out = c->start_embed (arrayZ); - if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ()); + if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ()); for (unsigned i = 0; i < length; i++) out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */ return_trace (hb_array_t (out, length)); } - template <typename hb_serialize_context_t, - typename U = Type, - hb_enable_if (sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>))> - hb_array_t copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - auto* out = c->start_embed (arrayZ); - if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ()); - hb_memcpy (out, arrayZ, get_size ()); - return_trace (hb_array_t (out, length)); - } - template <typename hb_sanitize_context_t> bool sanitize (hb_sanitize_context_t *c) const { return c->check_array (arrayZ, length); } @@ -312,8 +295,8 @@ hb_array (T (&array_)[length_]) template <typename Type> struct hb_sorted_array_t : - hb_array_t<Type>, - hb_iter_t<hb_sorted_array_t<Type>, Type&> + hb_iter_t<hb_sorted_array_t<Type>, Type&>, + hb_array_t<Type> { typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t; HB_ITER_USING (iter_base_t); @@ -333,8 +316,8 @@ struct hb_sorted_array_t : template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> constexpr hb_sorted_array_t (const hb_array_t<U> &o) : - hb_array_t<Type> (o), - hb_iter_t<hb_sorted_array_t, Type&> () {} + hb_iter_t<hb_sorted_array_t, Type&> (), + hb_array_t<Type> (o) {} template <typename U, hb_enable_if (hb_is_cr_convertible(U, Type))> hb_sorted_array_t& operator = (const hb_array_t<U> &o) @@ -346,11 +329,6 @@ struct hb_sorted_array_t : bool operator != (const hb_sorted_array_t& o) const { return this->arrayZ != o.arrayZ || this->length != o.length; } - /* Faster range-based for loop without bounds-check. */ - Type *begin () const { return this->arrayZ; } - Type *end () const { return this->arrayZ + this->length; } - - hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const { return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); } hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const @@ -443,42 +421,18 @@ inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const return 0 == hb_memcmp (arrayZ, o.arrayZ, length); } - -/* Specialize hash() for byte arrays. */ - template <> -inline uint32_t hb_array_t<const char>::hash () const -{ +inline uint32_t hb_array_t<const char>::hash () const { uint32_t current = 0; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); -#endif - - for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); + for (unsigned int i = 0; i < this->length; i++) + current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); return current; } - template <> -inline uint32_t hb_array_t<const unsigned char>::hash () const -{ +inline uint32_t hb_array_t<const unsigned char>::hash () const { uint32_t current = 0; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); -#endif - - for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); + for (unsigned int i = 0; i < this->length; i++) + current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); return current; } |