/* parse_blockquote • hanldes parsing of a blockquote fragment */ static size_t parse_blockquote(struct buf *ob, struct render *rndr, char *data, size_t size) { size_t beg, end = 0, pre, work_size = 0; char *work_data = 0; struct buf *out = new_work_buffer(rndr); beg = 0; while (beg < size) { for (end = beg + 1; end < size && data[end - 1] != '\n'; end += 1); pre = prefix_quote(data + beg, end - beg); if (pre) beg += pre; /* skipping prefix */ else if (is_empty(data + beg, end - beg) && (end >= size || (prefix_quote(data + end, size - end) == 0 && !is_empty(data + end, size - end)))) /* empty line followed by non-quote line */ break; if (beg < end) { /* copy into the in-place working buffer */ /* bufput(work, data + beg, end - beg); */ if (!work_data) work_data = data + beg; else if (data + beg != work_data + work_size) memmove(work_data + work_size, data + beg, end - beg); work_size += end - beg; } beg = end; } parse_block(out, rndr, work_data, work_size); if (rndr->make.blockquote) rndr->make.blockquote(ob, out, rndr->make.opaque); release_work_buffer(rndr, out); return end; }
/* parse_block • parsing of one block, returning next char to parse */ static void parse_block(struct buf *ob, struct render *rndr, char *data, size_t size) { size_t beg, end, i; char *txt_data; beg = 0; if (rndr->work.size > rndr->max_nesting) return; while (beg < size) { txt_data = data + beg; end = size - beg; if (data[beg] == '#') beg += parse_atxheader(ob, rndr, txt_data, end); else if (data[beg] == '<' && rndr->make.blockhtml && (i = parse_htmlblock(ob, rndr, txt_data, end, 1)) != 0) beg += i; else if ((i = is_empty(txt_data, end)) != 0) beg += i; else if (is_hrule(txt_data, end)) { if (rndr->make.hrule) rndr->make.hrule(ob, rndr->make.opaque); while (beg < size && data[beg] != '\n') beg++; beg++; } else if ((rndr->ext_flags & MKDEXT_FENCED_CODE) != 0 && (i = parse_fencedcode(ob, rndr, txt_data, end)) != 0) beg += i; else if ((rndr->ext_flags & MKDEXT_TABLES) != 0 && (i = parse_table(ob, rndr, txt_data, end)) != 0) beg += i; else if (prefix_quote(txt_data, end)) beg += parse_blockquote(ob, rndr, txt_data, end); else if (prefix_code(txt_data, end)) beg += parse_blockcode(ob, rndr, txt_data, end); else if (prefix_uli(txt_data, end)) beg += parse_list(ob, rndr, txt_data, end, 0); else if (prefix_oli(txt_data, end)) beg += parse_list(ob, rndr, txt_data, end, MKD_LIST_ORDERED); else beg += parse_paragraph(ob, rndr, txt_data, end); } }
/* parse_block • parsing of one block, returning next char to parse */ static void parse_block(struct buf *ob, struct render *rndr, char *data, size_t size) { size_t beg, end, i; char *txt_data; int has_table = (rndr->make.table && rndr->make.table_row && rndr->make.table_cell); if (rndr->work.size > rndr->make.max_work_stack) { if (size) bufput(ob, data, size); return; } beg = 0; while (beg < size) { txt_data = data + beg; end = size - beg; if (data[beg] == '#') beg += parse_atxheader(ob, rndr, txt_data, end); else if (data[beg] == '<' && rndr->make.blockhtml && (i = parse_htmlblock(ob, rndr, txt_data, end)) != 0) beg += i; else if ((i = is_empty(txt_data, end)) != 0) beg += i; else if (is_hrule(txt_data, end)) { if (rndr->make.hrule) rndr->make.hrule(ob, rndr->make.opaque); while (beg < size && data[beg] != '\n') beg += 1; beg += 1; } else if (prefix_quote(txt_data, end)) beg += parse_blockquote(ob, rndr, txt_data, end); else if (prefix_code(txt_data, end)) beg += parse_blockcode(ob, rndr, txt_data, end); else if (prefix_uli(txt_data, end)) beg += parse_list(ob, rndr, txt_data, end, 0); else if (prefix_oli(txt_data, end)) beg += parse_list(ob, rndr, txt_data, end, MKD_LIST_ORDERED); else if (has_table && is_tableline(txt_data, end)) beg += parse_table(ob, rndr, txt_data, end); else beg += parse_paragraph(ob, rndr, txt_data, end); } }