[serializer] Make snapshot()/revert() revert current object links

Fixes https://github.com/harfbuzz/harfbuzz/issues/2325
This commit is contained in:
Behdad Esfahbod 2020-04-18 16:29:32 -07:00
parent 6f6e78a26e
commit 2cc85281c2
1 changed files with 25 additions and 13 deletions

View File

@ -45,18 +45,13 @@ struct hb_serialize_context_t
{ {
typedef unsigned objidx_t; typedef unsigned objidx_t;
struct range_t
{
char *head, *tail;
};
enum whence_t { enum whence_t {
Head, /* Relative to the current object head (default). */ Head, /* Relative to the current object head (default). */
Tail, /* Relative to the current object tail after packed. */ Tail, /* Relative to the current object tail after packed. */
Absolute /* Absolute: from the start of the serialize buffer. */ Absolute /* Absolute: from the start of the serialize buffer. */
}; };
struct object_t : range_t struct object_t
{ {
void fini () { links.fini (); } void fini () { links.fini (); }
@ -83,12 +78,22 @@ struct hb_serialize_context_t
objidx_t objidx; objidx_t objidx;
}; };
char *head;
char *tail;
hb_vector_t<link_t> links; hb_vector_t<link_t> links;
object_t *next; 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) : hb_serialize_context_t (void *start_, unsigned int size) :
start ((char *) start_), start ((char *) start_),
@ -199,7 +204,7 @@ struct hb_serialize_context_t
object_t *obj = current; object_t *obj = current;
if (unlikely (!obj)) return; if (unlikely (!obj)) return;
current = current->next; current = current->next;
revert (*obj); revert (obj->head, obj->tail);
obj->fini (); obj->fini ();
object_pool.free (obj); object_pool.free (obj);
} }
@ -253,12 +258,19 @@ struct hb_serialize_context_t
return objidx; return objidx;
} }
void revert (range_t snap) void revert (snapshot_t snap)
{ {
assert (snap.head <= head); assert (snap.current == current);
assert (tail <= snap.tail); current->links.shrink (snap.num_links);
head = snap.head; revert (snap.head, snap.tail);
tail = snap.tail; }
void revert (char *snap_head,
char *snap_tail)
{
assert (snap_head <= head);
assert (tail <= snap_tail);
head = snap_head;
tail = snap_tail;
discard_stale_objects (); discard_stale_objects ();
} }