X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhb-serialize.hh;h=4fb4f4ef40a5d3a56881dbe79f14593f5f8100e6;hb=fe65a6a32ba3654c532639ba656bd66b041d7dc6;hp=4c674b1b1a46920a556444b7b44d8d3740e8c18d;hpb=a280f8312cc9b27515efbab292b95b9d147a2b73;p=platform%2Fupstream%2Fharfbuzz.git diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 4c674b1..4fb4f4e 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -45,12 +45,13 @@ struct hb_serialize_context_t { typedef unsigned objidx_t; - struct range_t - { - char *head, *tail; - }; + enum whence_t { + Head, /* Relative to the current object head (default). */ + Tail, /* Relative to the current object tail after packed. */ + Absolute /* Absolute: from the start of the serialize buffer. */ + }; - struct object_t : range_t + struct object_t { void fini () { links.fini (); } @@ -70,17 +71,29 @@ struct hb_serialize_context_t struct link_t { bool is_wide: 1; - unsigned position : 31; + bool is_signed: 1; + unsigned whence: 2; + unsigned position: 28; unsigned bias; objidx_t objidx; }; + char *head; + char *tail; hb_vector_t links; object_t *next; }; - range_t snapshot () { range_t s = {head, tail} ; return s; } + struct snapshot_t + { + char *head; + char *tail; + object_t *current; // Just for sanity check + unsigned num_links; + }; + snapshot_t snapshot () + { return snapshot_t { head, tail, current, current->links.length }; } hb_serialize_context_t (void *start_, unsigned int size) : start ((char *) start_), @@ -123,7 +136,7 @@ struct hb_serialize_context_t template bool check_equal (T1 &&v1, T2 &&v2) - { return check_success (v1 == v2); } + { return check_success ((long long) v1 == (long long) v2); } template bool check_assign (T1 &v1, T2 &&v2) @@ -166,7 +179,7 @@ struct hb_serialize_context_t if (packed.length <= 1) return; - pop_pack (); + pop_pack (false); resolve_links (); } @@ -191,11 +204,16 @@ struct hb_serialize_context_t object_t *obj = current; if (unlikely (!obj)) return; current = current->next; - revert (*obj); + revert (obj->head, obj->tail); obj->fini (); object_pool.free (obj); } - objidx_t pop_pack () + + /* Set share to false when an object is unlikely sharable with others + * so not worth an attempt, or a contiguous table is serialized as + * multiple consecutive objects in the reverse order so can't be shared. + */ + objidx_t pop_pack (bool share=true) { object_t *obj = current; if (unlikely (!obj)) return 0; @@ -211,11 +229,15 @@ struct hb_serialize_context_t return 0; } - objidx_t objidx = packed_map.get (obj); - if (objidx) + objidx_t objidx; + if (share) { - obj->fini (); - return objidx; + objidx = packed_map.get (obj); + if (objidx) + { + obj->fini (); + return objidx; + } } tail -= len; @@ -231,17 +253,24 @@ struct hb_serialize_context_t objidx = packed.length - 1; - packed_map.set (obj, objidx); + if (share) packed_map.set (obj, objidx); return objidx; } - void revert (range_t snap) + void revert (snapshot_t snap) + { + assert (snap.current == current); + current->links.shrink (snap.num_links); + revert (snap.head, snap.tail); + } + void revert (char *snap_head, + char *snap_tail) { - assert (snap.head <= head); - assert (tail <= snap.tail); - head = snap.head; - tail = snap.tail; + assert (snap_head <= head); + assert (tail <= snap_tail); + head = snap_head; + tail = snap_tail; discard_stale_objects (); } @@ -260,7 +289,9 @@ struct hb_serialize_context_t } template - void add_link (T &ofs, objidx_t objidx, const void *base = nullptr) + void add_link (T &ofs, objidx_t objidx, + whence_t whence = Head, + unsigned bias = 0) { static_assert (sizeof (T) == 2 || sizeof (T) == 4, ""); @@ -270,18 +301,24 @@ struct hb_serialize_context_t assert (current); assert (current->head <= (const char *) &ofs); - if (!base) - base = current->head; - else - assert (current->head <= (const char *) base); - auto& link = *current->links.push (); + link.is_wide = sizeof (T) == 4; + link.is_signed = hb_is_signed (hb_unwrap_type (T)); + link.whence = (unsigned) whence; link.position = (const char *) &ofs - current->head; - link.bias = (const char *) base - current->head; + link.bias = bias; link.objidx = objidx; } + unsigned to_bias (const void *base) const + { + if (!base) return 0; + assert (current); + assert (current->head <= (const char *) base); + return (const char *) base - current->head; + } + void resolve_links () { if (unlikely (in_error ())) return; @@ -293,20 +330,29 @@ struct hb_serialize_context_t for (const object_t::link_t &link : parent->links) { const object_t* child = packed[link.objidx]; - assert (link.bias <= (size_t) (parent->tail - parent->head)); - unsigned offset = (child->head - parent->head) - link.bias; + if (unlikely (!child)) { err_other_error(); return; } + unsigned offset = 0; + switch ((whence_t) link.whence) { + case Head: offset = child->head - parent->head; break; + case Tail: offset = child->head - parent->tail; break; + case Absolute: offset = (head - start) + (child->head - tail); break; + } - if (link.is_wide) + assert (offset >= link.bias); + offset -= link.bias; + if (link.is_signed) { - auto &off = * ((BEInt *) (parent->head + link.position)); - assert (0 == off); - check_assign (off, offset); + if (link.is_wide) + assign_offset (parent, link, offset); + else + assign_offset (parent, link, offset); } else { - auto &off = * ((BEInt *) (parent->head + link.position)); - assert (0 == off); - check_assign (off, offset); + if (link.is_wide) + assign_offset (parent, link, offset); + else + assign_offset (parent, link, offset); } } } @@ -387,6 +433,12 @@ struct hb_serialize_context_t Type *copy (const Type *src, Ts&&... ds) { return copy (*src, hb_forward (ds)...); } + template + void copy_all (Iterator it, Ts&&... ds) + { for (decltype (*it) _ : it) copy (_, hb_forward (ds)...); } + template hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; } @@ -441,6 +493,15 @@ struct hb_serialize_context_t (char *) b.arrayZ, free); } + private: + template + void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset) + { + auto &off = * ((BEInt *) (parent->head + link.position)); + assert (0 == off); + check_assign (off, offset); + } + public: /* TODO Make private. */ char *start, *head, *tail, *end; unsigned int debug_depth;