[use] Avoid O(n^2) in the machine

Fixes https://github.com/harfbuzz/harfbuzz/issues/3502
This commit is contained in:
Behdad Esfahbod 2022-03-23 17:30:25 -06:00
parent ccd9161bfd
commit a665e29ed7
3 changed files with 43 additions and 15 deletions

View File

@ -620,7 +620,7 @@ struct machine_index_t :
machine_index_t (const Iter& it) : it (it) {} machine_index_t (const Iter& it) : it (it) {}
machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>, machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
typename Iter::item_t> (), typename Iter::item_t> (),
it (o.it) {} it (o.it), is_null (o.is_null) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
@ -632,14 +632,28 @@ struct machine_index_t :
void __forward__ (unsigned n) { it += n; } void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; } void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; } void __rewind__ (unsigned n) { it -= n; }
void operator = (unsigned n) void operator = (unsigned n)
{ unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; } {
void operator = (const machine_index_t& o) { *this = (*o.it).first; } assert (n == 0);
bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; } is_null = true;
}
explicit operator bool () { return !is_null; }
void operator = (const machine_index_t& o)
{
is_null = o.is_null;
unsigned index = (*it).first;
unsigned n = (*o.it).first;
if (index < n) it += n - index; else if (index > n) it -= index - n;
}
bool operator == (const machine_index_t& o) const
{ return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
bool operator != (const machine_index_t& o) const { return !(*this == o); } bool operator != (const machine_index_t& o) const { return !(*this == o); }
private: private:
Iter it; Iter it;
bool is_null = false;
}; };
struct struct
{ {
@ -684,7 +698,7 @@ find_syllables_use (hb_buffer_t *buffer)
unsigned int act HB_UNUSED; unsigned int act HB_UNUSED;
int cs; int cs;
#line 688 "hb-ot-shape-complex-use-machine.hh" #line 702 "hb-ot-shape-complex-use-machine.hh"
{ {
cs = use_syllable_machine_start; cs = use_syllable_machine_start;
ts = 0; ts = 0;
@ -692,12 +706,12 @@ find_syllables_use (hb_buffer_t *buffer)
act = 0; act = 0;
} }
#line 267 "hb-ot-shape-complex-use-machine.rl" #line 281 "hb-ot-shape-complex-use-machine.rl"
unsigned int syllable_serial = 1; unsigned int syllable_serial = 1;
#line 701 "hb-ot-shape-complex-use-machine.hh" #line 715 "hb-ot-shape-complex-use-machine.hh"
{ {
int _slen; int _slen;
int _trans; int _trans;
@ -711,7 +725,7 @@ _resume:
#line 1 "NONE" #line 1 "NONE"
{ts = p;} {ts = p;}
break; break;
#line 715 "hb-ot-shape-complex-use-machine.hh" #line 729 "hb-ot-shape-complex-use-machine.hh"
} }
_keys = _use_syllable_machine_trans_keys + (cs<<1); _keys = _use_syllable_machine_trans_keys + (cs<<1);
@ -801,7 +815,7 @@ _eof_trans:
#line 170 "hb-ot-shape-complex-use-machine.rl" #line 170 "hb-ot-shape-complex-use-machine.rl"
{act = 2;} {act = 2;}
break; break;
#line 805 "hb-ot-shape-complex-use-machine.hh" #line 819 "hb-ot-shape-complex-use-machine.hh"
} }
_again: _again:
@ -810,7 +824,7 @@ _again:
#line 1 "NONE" #line 1 "NONE"
{ts = 0;} {ts = 0;}
break; break;
#line 814 "hb-ot-shape-complex-use-machine.hh" #line 828 "hb-ot-shape-complex-use-machine.hh"
} }
if ( ++p != pe ) if ( ++p != pe )
@ -826,7 +840,7 @@ _again:
} }
#line 272 "hb-ot-shape-complex-use-machine.rl" #line 286 "hb-ot-shape-complex-use-machine.rl"
} }

View File

@ -198,7 +198,7 @@ struct machine_index_t :
machine_index_t (const Iter& it) : it (it) {} machine_index_t (const Iter& it) : it (it) {}
machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>, machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
typename Iter::item_t> (), typename Iter::item_t> (),
it (o.it) {} it (o.it), is_null (o.is_null) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
@ -210,14 +210,28 @@ struct machine_index_t :
void __forward__ (unsigned n) { it += n; } void __forward__ (unsigned n) { it += n; }
void __prev__ () { --it; } void __prev__ () { --it; }
void __rewind__ (unsigned n) { it -= n; } void __rewind__ (unsigned n) { it -= n; }
void operator = (unsigned n) void operator = (unsigned n)
{ unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; } {
void operator = (const machine_index_t& o) { *this = (*o.it).first; } assert (n == 0);
bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; } is_null = true;
}
explicit operator bool () { return !is_null; }
void operator = (const machine_index_t& o)
{
is_null = o.is_null;
unsigned index = (*it).first;
unsigned n = (*o.it).first;
if (index < n) it += n - index; else if (index > n) it -= index - n;
}
bool operator == (const machine_index_t& o) const
{ return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
bool operator != (const machine_index_t& o) const { return !(*this == o); } bool operator != (const machine_index_t& o) const { return !(*this == o); }
private: private:
Iter it; Iter it;
bool is_null = false;
}; };
struct struct
{ {