/* hoedown_buffer_putc: appends a single uint8_t to a buffer */ void hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c) { assert(buf && buf->unit); if (buf->size + 1 > buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0) return; buf->data[buf->size] = c; buf->size += 1; }
void hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size) { assert(buf && buf->unit); if (buf->size + size > buf->asize) hoedown_buffer_grow(buf, buf->size + size); memcpy(buf->data + buf->size, data, size); buf->size += size; }
/* hoedown_buffer_put: appends raw data to a buffer */ void hoedown_buffer_put(hoedown_buffer *buf, const void *data, size_t len) { assert(buf && buf->unit); if (buf->size + len > buf->asize && hoedown_buffer_grow(buf, buf->size + len) < 0) return; memcpy(buf->data + buf->size, data, len); buf->size += len; }
void hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c) { assert(buf && buf->unit); if (buf->size >= buf->asize) hoedown_buffer_grow(buf, buf->size + 1); buf->data[buf->size] = c; buf->size += 1; }
/* hoedown_buffer_printf: formatted printing to a buffer */ void hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) { va_list ap; int n; assert(buf && buf->unit); if (buf->size >= buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0) return; va_start(ap, fmt); n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap); va_end(ap); if (n < 0) { #ifndef _MSC_VER return; #else va_start(ap, fmt); n = _vscprintf(fmt, ap); va_end(ap); #endif } if ((size_t)n >= buf->asize - buf->size) { if (hoedown_buffer_grow(buf, buf->size + n + 1) < 0) return; va_start(ap, fmt); n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap); va_end(ap); } if (n < 0) return; buf->size += n; }
const char * hoedown_buffer_cstr(hoedown_buffer *buf) { assert(buf && buf->unit); if (buf->size < buf->asize && buf->data[buf->size] == 0) return (char *)buf->data; hoedown_buffer_grow(buf, buf->size + 1); buf->data[buf->size] = 0; return (char *)buf->data; }
static void rndr_footnote_ref_def(hoedown_buffer *orig, const hoedown_renderer_data *data) { /* this is a little dirty, but it is simpler than maintaining this state in the renderer */ hoedown_buffer *copy; copy = hoedown_buffer_new(64); hoedown_buffer_grow(copy, orig->size); memcpy(copy->data, orig->data, orig->size); copy->size = orig->size; printf("Footnote Reference Definition: %s\n", hoedown_buffer_cstr(copy)); hoedown_buffer_free(copy); }
int main(int argc, char **argv) { struct hoedown_buffer *ib, *ob; FILE *in = stdin; struct hoedown_callbacks callbacks; struct hoedown_html_renderopt options; struct hoedown_markdown *markdown; /* opening the file if given from the command line */ if (argc > 1) { in = fopen(argv[1], "r"); if (!in) { fprintf(stderr, "Unable to open input file \"%s\": %s\n", argv[1], strerror(errno)); return 1; } } /* reading everything */ ib = hoedown_buffer_new(READ_UNIT); while (!feof(in) && !ferror(in)) { hoedown_buffer_grow(ib, ib->size + READ_UNIT); ib->size += fread(ib->data + ib->size, 1, READ_UNIT, in); } if (in != stdin) fclose(in); /* performing markdown parsing */ ob = hoedown_buffer_new(OUTPUT_UNIT); hoedown_html_renderer(&callbacks, &options, 0, 0); markdown = hoedown_markdown_new(0, 16, &callbacks, &options); hoedown_markdown_render(ob, ib->data, ib->size, markdown); hoedown_markdown_free(markdown); /* writing the result to stdout */ (void)fwrite(ob->data, 1, ob->size, stdout); /* cleanup */ hoedown_buffer_free(ib); hoedown_buffer_free(ob); return ferror(stdout); }
void hoedown_escape_html(struct hoedown_buffer *ob, const uint8_t *src, size_t size, int secure) { size_t i = 0, org, esc = 0; while (i < size) { org = i; while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) i++; if (i > org) { if (org == 0) { if (i >= size) { hoedown_buffer_put(ob, src, size); return; } hoedown_buffer_grow(ob, ESCAPE_GROW_FACTOR(size)); } hoedown_buffer_put(ob, src + org, i - org); } /* escaping */ if (i >= size) break; /* The forward slash is only escaped in secure mode */ if (src[i] == '/' && !secure) { hoedown_buffer_putc(ob, '/'); } else { hoedown_buffer_puts(ob, HTML_ESCAPES[esc]); } i++; } }
int main(int argc, char **argv) { int show_time = 0; //struct timespec start, end; /* buffers */ hoedown_buffer *ib, *ob; size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT; /* files */ FILE *in = NULL; /* renderer */ int toc_level = 0; int renderer_type = RENDERER_HTML; /* document */ hoedown_document *document; unsigned int extensions = 0; size_t max_nesting = DEF_MAX_NESTING; /* HTML renderer-specific */ unsigned int html_flags = 0; /* option parsing */ int just_args = 0; int i, j; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!arg[0]) continue; if (just_args || arg[0] != '-') { /* regular argument */ in = fopen(arg, "r"); if (!in) { fprintf(stderr, "Unable to open input file \"%s\": %s\n", arg, strerror(errno)); return 5; } continue; } if (!arg[1]) { /* arg is "-" */ in = stdin; continue; } if (arg[1] != '-') { /* parse short options */ char opt; const char *val; for (j = 1; (opt = arg[j]); j++) { if (opt == 'h') { print_help(argv[0]); return 1; } if (opt == 'v') { print_version(); return 1; } if (opt == 'T') { show_time = 1; continue; } /* options requiring value */ if (arg[++j]) val = arg+j; else if (argv[++i]) val = argv[i]; else { fprintf(stderr, "Wrong option '-%c' found.\n", opt); return 1; } long int num; int isNum = parseint(val, &num); if (opt == 'n' && isNum) { max_nesting = num; break; } if (opt == 't' && isNum) { toc_level = num; break; } if (opt == 'i' && isNum) { iunit = num; break; } if (opt == 'o' && isNum) { ounit = num; break; } fprintf(stderr, "Wrong option '-%c' found.\n", opt); return 1; } continue; } if (!arg[2]) { /* arg is "--" */ just_args = 1; continue; } /* parse long option */ char opt [100]; strncpy(opt, arg+2, 100); opt[99] = 0; char *val = strchr(opt, '='); long int num = 0; int isNum = 0; if (val) { *val = 0; val++; if (*val) isNum = parseint(val, &num); } int opt_parsed = 0; if (strcmp(opt, "help")==0) { print_help(argv[0]); return 1; } if (strcmp(opt, "version")==0) { print_version(); return 1; } if (strcmp(opt, "max-nesting")==0 && isNum) { opt_parsed = 1; max_nesting = num; } if (strcmp(opt, "toc-level")==0 && isNum) { opt_parsed = 1; toc_level = num; } if (strcmp(opt, "input-unit")==0 && isNum) { opt_parsed = 1; iunit = num; } if (strcmp(opt, "output-unit")==0 && isNum) { opt_parsed = 1; ounit = num; } if (strcmp(opt, "html")==0) { opt_parsed = 1; renderer_type = RENDERER_HTML; } if (strcmp(opt, "html-toc")==0) { opt_parsed = 1; renderer_type = RENDERER_HTML_TOC; } if (strcmp(opt, "null")==0) { opt_parsed = 1; renderer_type = RENDERER_NULL; } const char *name; size_t i; /* extension categories */ if ((name = strprefix(opt, category_prefix))) { for (i = 0; i < count_of(categories_info); i++) { struct extension_category_info *category = categories_info+i; if (strcmp(name, category->option_name)==0) { opt_parsed = 1; extensions |= category->flags; break; } } } /* extensions */ for (i = 0; i < count_of(extensions_info); i++) { struct extension_info *extension = extensions_info+i; if (strcmp(opt, extension->option_name)==0) { opt_parsed = 1; extensions |= extension->flag; break; } } /* html flags */ for (i = 0; i < count_of(html_flags_info); i++) { struct html_flag_info *html_flag = html_flags_info+i; if (strcmp(opt, html_flag->option_name)==0) { opt_parsed = 1; html_flags |= html_flag->flag; break; } } /* negations */ if ((name = strprefix(opt, negative_prefix))) { for (i = 0; i < count_of(categories_info); i++) { struct extension_category_info *category = categories_info+i; if (strcmp(name, category->option_name)==0) { opt_parsed = 1; extensions &= ~(category->flags); break; } } for (i = 0; i < count_of(extensions_info); i++) { struct extension_info *extension = extensions_info+i; if (strcmp(name, extension->option_name)==0) { opt_parsed = 1; extensions &= ~(extension->flag); break; } } for (i = 0; i < count_of(html_flags_info); i++) { struct html_flag_info *html_flag = html_flags_info+i; if (strcmp(name, html_flag->option_name)==0) { opt_parsed = 1; html_flags &= ~(html_flag->flag); break; } } } if (strcmp(opt, "time")==0) { opt_parsed = 1; show_time = 1; } if (!opt_parsed) { fprintf(stderr, "Wrong option '%s' found.\n", arg); return 1; } } if (!in) in = stdin; /* reading everything */ ib = hoedown_buffer_new(iunit); while (!feof(in)) { if (ferror(in)) { fprintf(stderr, "I/O errors found while reading input.\n"); return 5; } hoedown_buffer_grow(ib, ib->size + iunit); ib->size += fread(ib->data + ib->size, 1, iunit, in); } if (in != stdin) fclose(in); /* creating the renderer */ hoedown_renderer *renderer = NULL; void (*renderer_free)(hoedown_renderer*) = NULL; switch (renderer_type) { case RENDERER_HTML: renderer = hoedown_html_renderer_new(html_flags, toc_level); renderer_free = hoedown_html_renderer_free; break; case RENDERER_HTML_TOC: renderer = hoedown_html_toc_renderer_new(toc_level); renderer_free = hoedown_html_renderer_free; break; case RENDERER_NULL: renderer = null_renderer_new(); renderer_free = null_renderer_free; break; }; /* performing markdown rendering */ ob = hoedown_buffer_new(ounit); document = hoedown_document_new(renderer, extensions, max_nesting); //clock_gettime(CLOCK_MONOTONIC, &start); hoedown_document_render(document, ob, ib->data, ib->size); //clock_gettime(CLOCK_MONOTONIC, &end); /* writing the result to stdout */ (void)fwrite(ob->data, 1, ob->size, stdout); /* showing rendering time */ if (show_time) { //TODO: enable this //long long elapsed = ( end.tv_sec*1000000000 + end.tv_nsec) // - (start.tv_sec*1000000000 + start.tv_nsec); //if (elapsed < 1000000000) // fprintf(stderr, "Time spent on rendering: %.2f ms.\n", ((double)elapsed)/1000000); //else // fprintf(stderr, "Time spent on rendering: %.3f s.\n", ((double)elapsed)/1000000000); } /* cleanup */ hoedown_buffer_free(ib); hoedown_buffer_free(ob); hoedown_document_free(document); renderer_free(renderer); if (ferror(stdout)) { fprintf(stderr, "I/O errors found while writing output.\n"); return 5; } return 0; }
void hoedown_escape_href(struct hoedown_buffer *ob, const uint8_t *src, size_t size) { static const char hex_chars[] = "0123456789ABCDEF"; size_t i = 0, org; char hex_str[3]; hex_str[0] = '%'; while (i < size) { org = i; while (i < size && HREF_SAFE[src[i]] != 0) i++; if (i > org) { if (org == 0) { if (i >= size) { hoedown_buffer_put(ob, src, size); return; } hoedown_buffer_grow(ob, ESCAPE_GROW_FACTOR(size)); } hoedown_buffer_put(ob, src + org, i - org); } /* escaping */ if (i >= size) break; switch (src[i]) { /* amp appears all the time in URLs, but needs * HTML-entity escaping to be inside an href */ case '&': BUFPUTSL(ob, "&"); break; /* the single quote is a valid URL character * according to the standard; it needs HTML * entity escaping too */ case '\'': BUFPUTSL(ob, "'"); break; /* the space can be escaped to %20 or a plus * sign. we're going with the generic escape * for now. the plus thing is more commonly seen * when building GET strings */ #if 0 case ' ': hoedown_buffer_putc(ob, '+'); break; #endif /* every other character goes with a %XX escaping */ default: hex_str[1] = hex_chars[(src[i] >> 4) & 0xF]; hex_str[2] = hex_chars[src[i] & 0xF]; hoedown_buffer_put(ob, hex_str, 3); } i++; } }