Merge pull request #2163 from harfbuzz/absolute-link

added add_link_abs()
This commit is contained in:
Ebrahim Byagowi 2020-02-26 02:54:38 +03:30 committed by GitHub
commit c21eb86bfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 30 deletions

View File

@ -338,11 +338,15 @@ struct OffsetTo : Offset<OffsetType, has_null>
}
/* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
/* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029
* Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&...
*/
template <typename ...Ts>
bool serialize_copy (hb_serialize_context_t *c,
const OffsetTo& src,
const void *src_base,
const void *dst_base,
hb_serialize_context_t::whence_t whence,
Ts&&... ds)
{
*this = 0;
@ -353,11 +357,17 @@ struct OffsetTo : Offset<OffsetType, has_null>
bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
c->add_link (*this, c->pop_pack (), dst_base);
c->add_link (*this, c->pop_pack (), dst_base, whence);
return ret;
}
bool serialize_copy (hb_serialize_context_t *c,
const OffsetTo& src,
const void *src_base,
const void *dst_base)
{ return serialize_copy (c, src, src_base, dst_base, hb_serialize_context_t::Head); }
bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);

View File

@ -98,13 +98,12 @@ struct NameRecord
}
NameRecord* copy (hb_serialize_context_t *c,
const void *src_base,
const void *dst_base) const
const void *src_base) const
{
TRACE_SERIALIZE (this);
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
out->offset.serialize_copy (c, offset, src_base, dst_base, length);
out->offset.serialize_copy (c, offset, src_base, nullptr, hb_serialize_context_t::Tail, length);
return_trace (out);
}
@ -216,13 +215,6 @@ struct name
this->format = 0;
this->count = it.len ();
auto snap = c->snapshot ();
this->nameRecordZ.serialize (c, this->count);
if (unlikely (!c->check_assign (this->stringOffset, c->length ()))) return_trace (false);
c->revert (snap);
const void *dst_string_pool = &(this + this->stringOffset);
NameRecord *name_records = (NameRecord *) calloc (it.len (), NameRecord::static_size);
hb_array_t<NameRecord> records (name_records, it.len ());
@ -234,12 +226,12 @@ struct name
records.qsort ();
c->copy_all (records, src_string_pool, dst_string_pool);
c->copy_all (records, src_string_pool);
free (records.arrayZ);
if (unlikely (c->ran_out_of_room)) return_trace (false);
assert (this->stringOffset == c->length ());
this->stringOffset = c->length ();
return_trace (true);
}

View File

@ -50,6 +50,12 @@ struct hb_serialize_context_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
{
void fini () { links.fini (); }
@ -70,7 +76,9 @@ 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;
};
@ -269,7 +277,9 @@ struct hb_serialize_context_t
}
template <typename T>
void add_link (T &ofs, objidx_t objidx, const void *base = nullptr)
void add_link (T &ofs, objidx_t objidx,
const void *base = nullptr,
whence_t whence = Head)
{
static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
@ -279,15 +289,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;
if (whence == Head)
{
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;
}
@ -302,20 +321,28 @@ 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;
switch ((whence_t)link.whence) {
case Head: offset = (child->head - parent->head) - link.bias; break;
case Tail: offset = child->head - parent->tail; break;
case Absolute: offset = (head - start) + (child->head - tail); break;
default: assert (0);
}
if (link.is_wide)
if (link.is_signed)
{
auto &off = * ((BEInt<uint32_t, 4> *) (parent->head + link.position));
assert (0 == off);
check_assign (off, offset);
if (link.is_wide)
assign_offset<int32_t> (parent, link, offset);
else
assign_offset<int16_t> (parent, link, offset);
}
else
{
auto &off = * ((BEInt<uint16_t, 2> *) (parent->head + link.position));
assert (0 == off);
check_assign (off, offset);
if (link.is_wide)
assign_offset<uint32_t> (parent, link, offset);
else
assign_offset<uint16_t> (parent, link, offset);
}
}
}
@ -456,6 +483,15 @@ struct hb_serialize_context_t
(char *) b.arrayZ, free);
}
private:
template <typename T>
void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
{
auto &off = * ((BEInt<T, sizeof (T)> *) (parent->head + link.position));
assert (0 == off);
check_assign (off, offset);
}
public: /* TODO Make private. */
char *start, *head, *tail, *end;
unsigned int debug_depth;