diff options
author | John MacFarlane <jgm@berkeley.edu> | 2015-06-10 12:58:27 -0700 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2015-06-10 12:58:27 -0700 |
commit | e1db44b114620c5a23708d851d64fb53dd84bde9 (patch) | |
tree | 305c3d2382a0608af5874b5a80b1d43ecafcdb6e | |
parent | a79b2ed9b7051b259f1ab874e5168a853723c314 (diff) |
process_inlines: remove closers from delim stack when possible.
When they have no matching openers and cannot be openers themselves,
we can safely remove them.
This helps with a performance case: "a_ " * 20000.
See jgm/commonmark.js#43.
-rw-r--r-- | src/inlines.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/src/inlines.c b/src/inlines.c index 7e8f806..a1f0356 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -439,6 +439,8 @@ static void process_emphasis(subject *subj, delimiter *start_delim) { delimiter *closer = subj->last_delim; delimiter *opener; + delimiter *old_closer; + bool opener_not_found; // move back to first relevant delim. while (closer != NULL && closer->previous != start_delim) { @@ -459,6 +461,9 @@ static void process_emphasis(subject *subj, delimiter *start_delim) } opener = opener->previous; } + opener_not_found = opener == NULL || + opener == start_delim; + old_closer = closer; if (closer->delim_char == '*' || closer->delim_char == '_') { if (opener != NULL && opener != start_delim) { closer = S_insert_emph(subj, opener, closer); @@ -486,6 +491,12 @@ static void process_emphasis(subject *subj, delimiter *start_delim) } closer = closer->next; } + if (opener_not_found && !old_closer->can_open) { + // we can remove a closer that can't be an + // opener, once we've seen there's no + // matching opener: + remove_delimiter(subj, old_closer); + } } else { closer = closer->next; } |