diff options
author | John MacFarlane <jgm@berkeley.edu> | 2015-06-11 10:11:37 -0700 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2015-06-11 10:15:39 -0700 |
commit | 39b40151afa1af92c2d585c86930393be7e8ac73 (patch) | |
tree | e02ef08f18cceecba6c548d9a9fed0fdf5277307 | |
parent | 4224dc159cdd0b4429a566a14792c0abc0f5f62a (diff) |
Fixed `process_emphasis` to handle new pathological cases.
Now we have an array of pointers (`potential_openers`),
keyed to the delim char.
When we've failed to match a potential opener prior to point X
in the delimiter stack, we reset `potential_openers` for that opener
type to X, and thus avoid having to look again through all the openers
we've already rejected.
See jgm/commonmark#43.
-rw-r--r-- | src/inlines.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/inlines.c b/src/inlines.c index 7b51be9..0a75e38 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -441,6 +441,13 @@ static void process_emphasis(subject *subj, delimiter *start_delim) delimiter *opener; delimiter *old_closer; bool opener_found; + delimiter *potential_openers[128]; + + // initialize potential_openers: + potential_openers['*'] = start_delim; + potential_openers['_'] = start_delim; + potential_openers['\''] = start_delim; + potential_openers['"'] = start_delim; // move back to first relevant delim. while (closer != NULL && closer->previous != start_delim) { @@ -455,7 +462,7 @@ static void process_emphasis(subject *subj, delimiter *start_delim) // Now look backwards for first matching opener: opener = closer->previous; opener_found = false; - while (opener != NULL && opener != start_delim) { + while (opener != NULL && opener != potential_openers[closer->delim_char]) { if (opener->delim_char == closer->delim_char && opener->can_open) { opener_found = true; @@ -464,7 +471,13 @@ static void process_emphasis(subject *subj, delimiter *start_delim) opener = opener->previous; } old_closer = closer; - if (closer->delim_char == '*' || closer->delim_char == '_') { + if (closer->delim_char == '*') { + if (opener_found) { + closer = S_insert_emph(subj, opener, closer); + } else { + closer = closer->next; + } + } else if (closer->delim_char == '_') { if (opener_found) { closer = S_insert_emph(subj, opener, closer); } else { @@ -492,6 +505,8 @@ static void process_emphasis(subject *subj, delimiter *start_delim) closer = closer->next; } if (!opener_found && !old_closer->can_open) { + // set lower bound for future searches for openers: + potential_openers[old_closer->delim_char] = closer; // we can remove a closer that can't be an // opener, once we've seen there's no // matching opener: |