diff options
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-serialize.hh')
-rw-r--r-- | thirdparty/harfbuzz/src/hb-serialize.hh | 74 |
1 files changed, 55 insertions, 19 deletions
diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index cecdcdeb74..d5573281f1 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -139,6 +139,14 @@ struct hb_serialize_context_t objidx = o.objidx; } #endif + + HB_INTERNAL static int cmp (const void* a, const void* b) + { + int cmp = ((const link_t*)a)->position - ((const link_t*)b)->position; + if (cmp) return cmp; + + return ((const link_t*)a)->objidx - ((const link_t*)b)->objidx; + } }; char *head; @@ -186,7 +194,6 @@ struct hb_serialize_context_t current = current->next; _->fini (); } - object_pool.fini (); } bool in_error () const { return bool (errors); } @@ -216,6 +223,7 @@ struct hb_serialize_context_t this->errors = HB_SERIALIZE_ERROR_NONE; this->head = this->start; this->tail = this->end; + this->zerocopy = nullptr; this->debug_depth = 0; fini (); @@ -315,10 +323,11 @@ struct hb_serialize_context_t { object_t *obj = current; if (unlikely (!obj)) return; - if (unlikely (in_error())) return; + if (unlikely (in_error() && !only_overflow ())) return; current = current->next; - revert (obj->head, obj->tail); + revert (zerocopy ? zerocopy : obj->head, obj->tail); + zerocopy = nullptr; obj->fini (); object_pool.release (obj); } @@ -336,8 +345,11 @@ struct hb_serialize_context_t current = current->next; obj->tail = head; obj->next = nullptr; + assert (obj->head <= obj->tail); unsigned len = obj->tail - obj->head; - head = obj->head; /* Rewind head. */ + head = zerocopy ? zerocopy : obj->head; /* Rewind head. */ + bool was_zerocopy = zerocopy; + zerocopy = nullptr; if (!len) { @@ -347,9 +359,11 @@ struct hb_serialize_context_t } objidx_t objidx; + uint32_t hash = 0; if (share) { - objidx = packed_map.get (obj); + hash = hb_hash (obj); + objidx = packed_map.get_with_hash (obj, hash); if (objidx) { merge_virtual_links (obj, objidx); @@ -359,7 +373,10 @@ struct hb_serialize_context_t } tail -= len; - memmove (tail, obj->head, len); + if (was_zerocopy) + assert (tail == obj->head); + else + memmove (tail, obj->head, len); obj->head = tail; obj->tail = tail + len; @@ -377,7 +394,7 @@ struct hb_serialize_context_t objidx = packed.length - 1; - if (share) packed_map.set (obj, objidx); + if (share) packed_map.set_with_hash (obj, hash, objidx); propagate_error (packed_map); return objidx; @@ -561,8 +578,26 @@ struct hb_serialize_context_t return !bool ((errors = (errors | err_type))); } + bool start_zerocopy (size_t size) + { + if (unlikely (in_error ())) return false; + + if (unlikely (size > INT_MAX || this->tail - this->head < ptrdiff_t (size))) + { + err (HB_SERIALIZE_ERROR_OUT_OF_ROOM); + return false; + } + + assert (!this->zerocopy); + this->zerocopy = this->head; + + assert (this->current->head == this->head); + this->current->head = this->current->tail = this->head = this->tail - size; + return true; + } + template <typename Type> - Type *allocate_size (size_t size) + Type *allocate_size (size_t size, bool clear = true) { if (unlikely (in_error ())) return nullptr; @@ -571,7 +606,8 @@ struct hb_serialize_context_t err (HB_SERIALIZE_ERROR_OUT_OF_ROOM); return nullptr; } - hb_memset (this->head, 0, size); + if (clear) + hb_memset (this->head, 0, size); char *ret = this->head; this->head += size; return reinterpret_cast<Type *> (ret); @@ -585,9 +621,9 @@ struct hb_serialize_context_t Type *embed (const Type *obj) { unsigned int size = obj->get_size (); - Type *ret = this->allocate_size<Type> (size); + Type *ret = this->allocate_size<Type> (size, false); if (unlikely (!ret)) return nullptr; - memcpy (ret, obj, size); + hb_memcpy (ret, obj, size); return ret; } template <typename Type> @@ -608,7 +644,7 @@ struct hb_serialize_context_t } /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data - * instead of memcpy(). */ + * instead of hb_memcpy(). */ template <typename Type, typename ...Ts> Type *copy (const Type &src, Ts&&... ds) { return _copy (src, hb_prioritize, std::forward<Ts> (ds)...); } @@ -626,7 +662,7 @@ struct hb_serialize_context_t hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; } template <typename Type> - Type *extend_size (Type *obj, size_t size) + Type *extend_size (Type *obj, size_t size, bool clear = true) { if (unlikely (in_error ())) return nullptr; @@ -634,12 +670,12 @@ struct hb_serialize_context_t assert ((char *) obj <= this->head); assert ((size_t) (this->head - (char *) obj) <= size); if (unlikely (((char *) obj + size < (char *) obj) || - !this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr; + !this->allocate_size<Type> (((char *) obj) + size - this->head, clear))) return nullptr; return reinterpret_cast<Type *> (obj); } template <typename Type> - Type *extend_size (Type &obj, size_t size) - { return extend_size (std::addressof (obj), size); } + Type *extend_size (Type &obj, size_t size, bool clear = true) + { return extend_size (std::addressof (obj), size, clear); } template <typename Type> Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); } @@ -668,8 +704,8 @@ struct hb_serialize_context_t char *p = (char *) hb_malloc (len); if (unlikely (!p)) return hb_bytes_t (); - memcpy (p, this->start, this->head - this->start); - memcpy (p + (this->head - this->start), this->tail, this->end - this->tail); + hb_memcpy (p, this->start, this->head - this->start); + hb_memcpy (p + (this->head - this->start), this->tail, this->end - this->tail); return hb_bytes_t (p, len); } template <typename Type> @@ -696,7 +732,7 @@ struct hb_serialize_context_t } public: - char *start, *head, *tail, *end; + char *start, *head, *tail, *end, *zerocopy; unsigned int debug_depth; hb_serialize_error_t errors; |