add "add_link()" with bias arg

issue #2227
This commit is contained in:
blueshade7 2020-03-05 15:40:44 -08:00 committed by Ebrahim Byagowi
parent bdf372b24c
commit 4c3af7d406
2 changed files with 22 additions and 17 deletions

View File

@ -415,7 +415,7 @@ struct Dict : UnsizedByteStr
{ {
T &ofs = *(T *) (c->head + OpCode_Size (int_op)); T &ofs = *(T *) (c->head + OpCode_Size (int_op));
if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false; if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false;
c->add_link (ofs, link, nullptr, whence); c->add_link (ofs, link, whence);
return true; return true;
} }

View File

@ -278,8 +278,8 @@ struct hb_serialize_context_t
template <typename T> template <typename T>
void add_link (T &ofs, objidx_t objidx, void add_link (T &ofs, objidx_t objidx,
const void *base = nullptr, whence_t whence,
whence_t whence = Head) unsigned bias = 0)
{ {
static_assert (sizeof (T) == 2 || sizeof (T) == 4, ""); static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
@ -293,23 +293,18 @@ struct hb_serialize_context_t
link.is_wide = sizeof (T) == 4; link.is_wide = sizeof (T) == 4;
link.is_signed = hb_is_signed (hb_unwrap_type (T)); link.is_signed = hb_is_signed (hb_unwrap_type (T));
link.whence = (unsigned)whence; link.whence = (unsigned) whence;
link.position = (const char *) &ofs - current->head; link.position = (const char *) &ofs - current->head;
if (whence == Head) link.bias = bias;
{
if (base == nullptr)
link.bias = 0;
else
{
assert (current->head <= (const char *)base);
link.bias = (const char *) base - current->head;
}
}
else
link.bias = 0;
link.objidx = objidx; link.objidx = objidx;
} }
template <typename T>
void add_link (T &ofs, objidx_t objidx,
const void *base = nullptr,
whence_t whence = Head)
{ add_link (ofs, objidx, whence, to_bias (base)); }
void resolve_links () void resolve_links ()
{ {
if (unlikely (in_error ())) return; if (unlikely (in_error ())) return;
@ -324,12 +319,14 @@ struct hb_serialize_context_t
if (unlikely (!child)) { err_other_error(); return; } if (unlikely (!child)) { err_other_error(); return; }
unsigned offset; unsigned offset;
switch ((whence_t)link.whence) { switch ((whence_t)link.whence) {
case Head: offset = (child->head - parent->head) - link.bias; break; case Head: offset = child->head - parent->head; break;
case Tail: offset = child->head - parent->tail; break; case Tail: offset = child->head - parent->tail; break;
case Absolute: offset = (head - start) + (child->head - tail); break; case Absolute: offset = (head - start) + (child->head - tail); break;
default: assert (0); default: assert (0);
} }
assert (offset >= link.bias);
offset -= link.bias;
if (link.is_signed) if (link.is_signed)
{ {
if (link.is_wide) if (link.is_wide)
@ -492,6 +489,14 @@ struct hb_serialize_context_t
check_assign (off, offset); check_assign (off, offset);
} }
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;
}
public: /* TODO Make private. */ public: /* TODO Make private. */
char *start, *head, *tail, *end; char *start, *head, *tail, *end;
unsigned int debug_depth; unsigned int debug_depth;