[subset] Refactor _subset () to reduce nesting and eliminate the use of 'goto'.

This commit is contained in:
Garret Rieger 2020-11-10 16:15:37 -08:00
parent bb5c80a7c2
commit 832f2b599b
3 changed files with 92 additions and 56 deletions

View File

@ -119,6 +119,14 @@ struct hb_serialize_context_t
bool in_error () const { return !this->successful; }
void reset (void *start_, unsigned int size)
{
start = (char*) start_;
end = start + size;
reset ();
current = nullptr;
}
void reset ()
{
this->successful = true;
@ -129,6 +137,7 @@ struct hb_serialize_context_t
fini ();
this->packed.push (nullptr);
this->packed_map.init ();
}
bool check_success (bool success)

View File

@ -94,74 +94,100 @@ _repack (hb_tag_t tag, const hb_serialize_context_t& c)
return repacked.copy_blob ();
}
template<typename TableType>
static
bool
_try_subset (const TableType *table,
hb_vector_t<char>* buf,
unsigned buf_size,
hb_subset_context_t* c /* OUT */)
{
c->serializer->start_serialize<TableType> ();
bool needed = table->subset (c);
if (!c->serializer->ran_out_of_room)
{
c->serializer->end_serialize ();
return needed;
}
buf_size += (buf_size >> 1) + 32;
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
if (unlikely (!buf->alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
return needed;
}
c->serializer->reset (buf->arrayZ, buf_size);
return _try_subset (table, buf, buf_size, c);
}
template<typename TableType>
static bool
_subset (hb_subset_plan_t *plan)
{
bool result = false;
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
const TableType *table = source_blob->as<TableType> ();
hb_tag_t tag = TableType::tableTag;
if (source_blob->data)
if (!source_blob->data)
{
hb_vector_t<char> buf;
/* TODO Not all tables are glyph-related. 'name' table size for example should not be
* affected by number of glyphs. Accommodate that. */
unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
hb_blob_destroy (source_blob);
return false;
}
retry:
hb_serialize_context_t serializer ((void *) buf, buf_size);
serializer.start_serialize<TableType> ();
hb_subset_context_t c (source_blob, plan, &serializer, tag);
bool needed = table->subset (&c);
if (serializer.ran_out_of_room)
{
buf_size += (buf_size >> 1) + 32;
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
hb_blob_destroy (source_blob);
return false;
}
goto retry;
}
serializer.end_serialize ();
result = !serializer.in_error ();
if (result)
{
if (needed)
{
hb_blob_t *dest_blob = _repack (tag, serializer);
if (dest_blob)
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
result = c.plan->add_table (tag, dest_blob);
hb_blob_destroy (dest_blob);
} else {
result = false;
}
}
else
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
}
}
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
hb_blob_destroy (source_blob);
return false;
}
else
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
hb_vector_t<char> buf;
/* TODO Not all tables are glyph-related. 'name' table size for example should not be
* affected by number of glyphs. Accommodate that. */
unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
hb_blob_destroy (source_blob);
return false;
}
bool needed = false;
hb_serialize_context_t serializer (buf.arrayZ, buf_size);
{
hb_subset_context_t c (source_blob, plan, &serializer, tag);
needed = _try_subset (table, &buf, buf_size, &c);
}
hb_blob_destroy (source_blob);
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
if (serializer.ran_out_of_room || serializer.in_error ())
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag));
return false;
}
if (!needed)
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
return true;
}
bool result = false;
hb_blob_t *dest_blob = _repack (tag, serializer);
if (dest_blob)
{
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c final subset table size: %u bytes.",
HB_UNTAG (tag), dest_blob->length);
result = plan->add_table (tag, dest_blob);
hb_blob_destroy (dest_blob);
}
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s",
HB_UNTAG (tag), result ? "success" : "FAILED!");
return result;
}

View File

@ -478,6 +478,7 @@ if get_option('tests').enabled()
'test-algs': ['test-algs.cc', 'hb-static.cc'],
'test-array': ['test-array.cc'],
'test-repacker': ['test-repacker.cc', 'hb-static.cc'],
'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
'test-iter': ['test-iter.cc', 'hb-static.cc'],
'test-meta': ['test-meta.cc', 'hb-static.cc'],
'test-number': ['test-number.cc', 'hb-number.cc'],