From a6b90a7cf7fd517b3c7d37cd824e11f9ad544b8c Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Tue, 2 Sep 2014 19:21:58 +0200 Subject: [PATCH 01/17] Import improvements from Lanli (and more things) --- Makefile | 2 +- bin/hoedown.c | 30 +--------- bin/smartypants.c | 13 +---- src/autolink.c | 17 +++--- src/autolink.h | 37 +++++++----- src/buffer.c | 117 ++++++++++++++++++++------------------ src/buffer.h | 88 +++++++++++++++++++++-------- src/document.c | 101 ++++++++++++++------------------- src/document.h | 71 +++++++++++------------ src/escape.c | 140 +++++++++++++++++++++++----------------------- src/escape.h | 13 ++++- src/html.c | 62 ++++++++------------ src/html.h | 52 +++++++++++------ src/stack.c | 63 +++++++++++---------- src/stack.h | 37 +++++++++--- src/version.h | 15 ++++- 16 files changed, 458 insertions(+), 400 deletions(-) diff --git a/Makefile b/Makefile index 998a41d4..fb0f79c7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -g -O3 -Wall -Wextra -Wno-unused-parameter -Isrc +CFLAGS = -g -O3 -Wall -Wextra -Wno-unused-parameter -Isrc -std=c99 ifneq ($(OS),Windows_NT) CFLAGS += -fPIC diff --git a/bin/hoedown.c b/bin/hoedown.c index 1440c551..3a3fc745 100644 --- a/bin/hoedown.c +++ b/bin/hoedown.c @@ -399,20 +399,13 @@ main(int argc, char **argv) /* reading everything */ ib = hoedown_buffer_new(iunit); - if (!ib) { - fprintf(stderr, "Couldn't allocate input buffer.\n"); - return 4; - } while (!feof(in)) { if (ferror(in)) { fprintf(stderr, "I/O errors found while reading input.\n"); return 5; } - if (hoedown_buffer_grow(ib, ib->size + iunit) != HOEDOWN_BUF_OK) { - fprintf(stderr, "Couldn't grow input buffer.\n"); - return 4; - } + hoedown_buffer_grow(ib, ib->size + iunit); ib->size += fread(ib->data + ib->size, 1, iunit, in); } @@ -421,8 +414,8 @@ main(int argc, char **argv) /* creating the renderer */ - hoedown_renderer *renderer; - void (*renderer_free)(hoedown_renderer*); + hoedown_renderer *renderer = NULL; + void (*renderer_free)(hoedown_renderer*) = NULL; switch (renderer_type) { case RENDERER_HTML: @@ -437,29 +430,12 @@ main(int argc, char **argv) renderer = null_renderer_new(); renderer_free = null_renderer_free; break; - default: - renderer = NULL; - renderer_free = NULL; }; - if (!renderer) { - fprintf(stderr, "Couldn't allocate renderer.\n"); - return 4; - } - /* performing markdown rendering */ ob = hoedown_buffer_new(ounit); - if (!ob) { - fprintf(stderr, "Couldn't allocate output buffer.\n"); - return 4; - } - document = hoedown_document_new(renderer, extensions, max_nesting); - if (!document) { - fprintf(stderr, "Couldn't allocate document parser.\n"); - return 4; - } //clock_gettime(CLOCK_MONOTONIC, &start); hoedown_document_render(document, ob, ib->data, ib->size); diff --git a/bin/smartypants.c b/bin/smartypants.c index 55501570..c7ba4c13 100644 --- a/bin/smartypants.c +++ b/bin/smartypants.c @@ -183,20 +183,13 @@ main(int argc, char **argv) /* reading everything */ ib = hoedown_buffer_new(iunit); - if (!ib) { - fprintf(stderr, "Couldn't allocate input buffer.\n"); - return 4; - } while (!feof(in)) { if (ferror(in)) { fprintf(stderr, "I/O errors found while reading input.\n"); return 5; } - if (hoedown_buffer_grow(ib, ib->size + iunit) != HOEDOWN_BUF_OK) { - fprintf(stderr, "Couldn't grow input buffer.\n"); - return 4; - } + hoedown_buffer_grow(ib, ib->size + iunit); ib->size += fread(ib->data + ib->size, 1, iunit, in); } @@ -206,10 +199,6 @@ main(int argc, char **argv) /* performing SmartyPants processing */ ob = hoedown_buffer_new(ounit); - if (!ob) { - fprintf(stderr, "Couldn't allocate output buffer.\n"); - return 4; - } //clock_gettime(CLOCK_MONOTONIC, &start); hoedown_html_smartypants(ob, ib->data, ib->size); diff --git a/src/autolink.c b/src/autolink.c index f2245cb0..5d18fb53 100644 --- a/src/autolink.c +++ b/src/autolink.c @@ -10,21 +10,20 @@ #endif int -hoedown_autolink_is_safe(const uint8_t *link, size_t link_len) +hoedown_autolink_is_safe(const uint8_t *data, size_t size) { static const size_t valid_uris_count = 6; static const char *valid_uris[] = { - "#", "/", "http://", "https://", "ftp://", "mailto:" + "http://", "https://", "/", "#", "ftp://", "mailto:" }; + static const size_t valid_uris_size[] = { 7, 8, 1, 1, 6, 7 }; - size_t i; - - for (i = 0; i < valid_uris_count; ++i) { - size_t len = strlen(valid_uris[i]); + for (size_t i = 0; i < valid_uris_count; ++i) { + size_t len = valid_uris_size[i]; - if (link_len > len && - strncasecmp((char *)link, valid_uris[i], len) == 0 && - isalnum(link[len])) + if (size > len && + strncasecmp((char *)data, valid_uris[i], len) == 0 && + isalnum(data[len])) return 1; } diff --git a/src/autolink.h b/src/autolink.h index 8860ee20..528885c9 100644 --- a/src/autolink.h +++ b/src/autolink.h @@ -9,24 +9,35 @@ extern "C" { #endif -enum { + +/************* + * CONSTANTS * + *************/ + +typedef enum hoedown_autolink_flags { HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0) -}; +} hoedown_autolink_flags; + + +/************* + * FUNCTIONS * + *************/ + +/* hoedown_autolink_is_safe: verify that a URL has a safe protocol */ +int hoedown_autolink_is_safe(const uint8_t *data, size_t size); -int -hoedown_autolink_is_safe(const uint8_t *link, size_t link_len); +/* hoedown_autolink__www: search for the next www link in data */ +size_t hoedown_autolink__www(size_t *rewind_p, hoedown_buffer *link, + uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags); -size_t -hoedown_autolink__www(size_t *rewind_p, hoedown_buffer *link, - uint8_t *data, size_t offset, size_t size, unsigned int flags); +/* hoedown_autolink__email: search for the next email in data */ +size_t hoedown_autolink__email(size_t *rewind_p, hoedown_buffer *link, + uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags); -size_t -hoedown_autolink__email(size_t *rewind_p, hoedown_buffer *link, - uint8_t *data, size_t offset, size_t size, unsigned int flags); +/* hoedown_autolink__url: search for the next URL in data */ +size_t hoedown_autolink__url(size_t *rewind_p, hoedown_buffer *link, + uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags); -size_t -hoedown_autolink__url(size_t *rewind_p, hoedown_buffer *link, - uint8_t *data, size_t offset, size_t size, unsigned int flags); #ifdef __cplusplus } diff --git a/src/buffer.c b/src/buffer.c index 1ab9eac5..6e96224b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5,7 +5,6 @@ #include #include -/* hoedown_buffer_init: initialize a buffer with custom allocators */ void hoedown_buffer_init( hoedown_buffer *buf, @@ -14,8 +13,7 @@ hoedown_buffer_init( hoedown_free_callback data_free, hoedown_free_callback buffer_free) { - if (!buf) - return; + assert(buf); buf->data = NULL; buf->size = buf->asize = 0; @@ -25,21 +23,18 @@ hoedown_buffer_init( buf->buffer_free = buffer_free; } -/* hoedown_buffer_new: allocation of a new buffer */ hoedown_buffer * hoedown_buffer_new(size_t unit) { - hoedown_buffer *ret = malloc(sizeof (hoedown_buffer)); - hoedown_buffer_init(ret, unit, realloc, free, free); + hoedown_buffer *ret = hoedown_malloc(sizeof (hoedown_buffer)); + hoedown_buffer_init(ret, unit, hoedown_realloc, free, free); return ret; } -/* hoedown_buffer_free: decrease the reference count and free the buffer if needed */ void hoedown_buffer_free(hoedown_buffer *buf) { - if (!buf) - return; + if (!buf) return; buf->data_free(buf->data); @@ -47,84 +42,104 @@ hoedown_buffer_free(hoedown_buffer *buf) buf->buffer_free(buf); } -/* hoedown_buffer_reset: frees internal data of the buffer */ void hoedown_buffer_reset(hoedown_buffer *buf) { - if (!buf) - return; + assert(buf && buf->unit); buf->data_free(buf->data); buf->data = NULL; buf->size = buf->asize = 0; } -/* hoedown_buffer_grow: increasing the allocated size to the given value */ -int +void hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz) { size_t neoasz; - void *neodata; - assert(buf && buf->unit); if (buf->asize >= neosz) - return HOEDOWN_BUF_OK; + return; neoasz = buf->asize + buf->unit; while (neoasz < neosz) neoasz += buf->unit; - neodata = buf->data_realloc(buf->data, neoasz); - if (!neodata) - return HOEDOWN_BUF_ENOMEM; - - buf->data = neodata; + buf->data = buf->data_realloc(buf->data, neoasz); buf->asize = neoasz; - return HOEDOWN_BUF_OK; } -/* hoedown_buffer_put: appends raw data to a buffer */ void -hoedown_buffer_put(hoedown_buffer *buf, const void *data, size_t len) +hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size) { assert(buf && buf->unit); - if (buf->size + len > buf->asize && hoedown_buffer_grow(buf, buf->size + len) < 0) - return; + if (buf->size + size > buf->asize) + hoedown_buffer_grow(buf, buf->size + size); - memcpy(buf->data + buf->size, data, len); - buf->size += len; + memcpy(buf->data + buf->size, data, size); + buf->size += size; } -/* hoedown_buffer_puts: appends a NUL-terminated string to a buffer */ void hoedown_buffer_puts(hoedown_buffer *buf, const char *str) { - hoedown_buffer_put(buf, str, strlen(str)); + hoedown_buffer_put(buf, (const uint8_t *)str, strlen(str)); } - -/* 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; + if (buf->size >= buf->asize) + hoedown_buffer_grow(buf, buf->size + 1); buf->data[buf->size] = c; buf->size += 1; } +void +hoedown_buffer_set(hoedown_buffer *buf, const uint8_t *data, size_t size) +{ + assert(buf && buf->unit); + + if (size > buf->asize) + hoedown_buffer_grow(buf, size); + + memcpy(buf->data, data, size); + buf->size = size; +} + +void +hoedown_buffer_sets(hoedown_buffer *buf, const char *str) +{ + hoedown_buffer_set(buf, (const uint8_t *)str, strlen(str)); +} + +int +hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size) +{ + if (buf->size != size) return 0; + + size_t i = 0; + while (i < size && buf->data[i] == data[i]) i++; + + return i == size; +} + +int +hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str) +{ + return hoedown_buffer_eq(buf, (const uint8_t *)str, strlen(str)); +} + int hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix) { - size_t i; assert(buf && buf->unit); - for (i = 0; i < buf->size; ++i) { + for (size_t i = 0; i < buf->size; ++i) { if (prefix[i] == 0) return 0; @@ -135,22 +150,20 @@ hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix) return 0; } -/* hoedown_buffer_slurp: removes a given number of bytes from the head of the array */ void -hoedown_buffer_slurp(hoedown_buffer *buf, size_t len) +hoedown_buffer_slurp(hoedown_buffer *buf, size_t size) { assert(buf && buf->unit); - if (len >= buf->size) { + if (size >= buf->size) { buf->size = 0; return; } - buf->size -= len; - memmove(buf->data, buf->data + len, buf->size); + buf->size -= size; + memmove(buf->data, buf->data + size, buf->size); } -/* hoedown_buffer_cstr: NULL-termination of the string array */ const char * hoedown_buffer_cstr(hoedown_buffer *buf) { @@ -159,15 +172,12 @@ hoedown_buffer_cstr(hoedown_buffer *buf) if (buf->size < buf->asize && buf->data[buf->size] == 0) return (char *)buf->data; - if (buf->size + 1 <= buf->asize || hoedown_buffer_grow(buf, buf->size + 1) == 0) { - buf->data[buf->size] = 0; - return (char *)buf->data; - } + hoedown_buffer_grow(buf, buf->size + 1); + buf->data[buf->size] = 0; - return NULL; + return (char *)buf->data; } -/* hoedown_buffer_printf: formatted printing to a buffer */ void hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) { @@ -176,9 +186,9 @@ hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) assert(buf && buf->unit); - if (buf->size >= buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0) - return; - + if (buf->size >= buf->asize) + hoedown_buffer_grow(buf, buf->size + 1); + va_start(ap, fmt); n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap); va_end(ap); @@ -194,8 +204,7 @@ hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) } if ((size_t)n >= buf->asize - buf->size) { - if (hoedown_buffer_grow(buf, buf->size + n + 1) < 0) - return; + hoedown_buffer_grow(buf, buf->size + n + 1); va_start(ap, fmt); n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap); diff --git a/src/buffer.h b/src/buffer.h index 8ba36832..5cc074d4 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -3,9 +3,11 @@ #ifndef HOEDOWN_BUFFER_H #define HOEDOWN_BUFFER_H +#include #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -16,15 +18,14 @@ extern "C" { #define inline __inline #endif -typedef enum { - HOEDOWN_BUF_OK = 0, - HOEDOWN_BUF_ENOMEM = -1 -} hoedown_buferror_t; + +/********* + * TYPES * + *********/ typedef void *(*hoedown_realloc_callback)(void *, size_t); typedef void (*hoedown_free_callback)(void *); -/* hoedown_buffer: character array buffer */ struct hoedown_buffer { uint8_t *data; /* actual character data */ size_t size; /* size of the string */ @@ -35,12 +36,29 @@ struct hoedown_buffer { hoedown_free_callback data_free; hoedown_free_callback buffer_free; }; - typedef struct hoedown_buffer hoedown_buffer; -/* HOEDOWN_BUFPUTSL: optimized hoedown_buffer_puts of a string literal */ -#define HOEDOWN_BUFPUTSL(output, literal) \ - hoedown_buffer_put(output, literal, sizeof(literal) - 1) +/* malloc / realloc / calloc wrappers */ +#define HOEDOWN_ALLOC_WRAPPER(sig, call) \ + static inline void *hoedown_##sig __attribute__ ((malloc)); \ + static inline void *hoedown_##sig { \ + void *ret = call; \ + if (!ret) { \ + fprintf(stderr, "Allocation failed.\n"); \ + abort(); \ + } \ + return ret; \ + } + + +/************* + * FUNCTIONS * + *************/ + +/* allocation wrappers */ +HOEDOWN_ALLOC_WRAPPER(malloc(size_t size), malloc(size)); +HOEDOWN_ALLOC_WRAPPER(calloc(size_t nmemb, size_t size), calloc(nmemb, size)); +HOEDOWN_ALLOC_WRAPPER(realloc(void *ptr, size_t size), realloc(ptr, size)); /* hoedown_buffer_init: initialize a buffer with custom allocators */ void hoedown_buffer_init( @@ -51,32 +69,41 @@ void hoedown_buffer_init( hoedown_free_callback buffer_free ); -/* hoedown_buffer_new: allocation of a new buffer */ +/* hoedown_buffer_new: allocate a new buffer */ hoedown_buffer *hoedown_buffer_new(size_t unit) __attribute__ ((malloc)); -/* hoedown_buffer_free: decrease the reference count and free the buffer if needed */ -void hoedown_buffer_free(hoedown_buffer *buf); - -/* hoedown_buffer_reset: frees internal data of the buffer */ +/* hoedown_buffer_reset: free internal data of the buffer */ void hoedown_buffer_reset(hoedown_buffer *buf); -/* hoedown_buffer_grow: increasing the allocated size to the given value */ -int hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz); +/* hoedown_buffer_grow: increase the allocated size to the given value */ +void hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz); -/* hoedown_buffer_put: appends raw data to a buffer */ -void hoedown_buffer_put(hoedown_buffer *buf, const void *data, size_t len); +/* hoedown_buffer_put: append raw data to a buffer */ +void hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size); -/* hoedown_buffer_puts: appends a NUL-terminated string to a buffer */ +/* hoedown_buffer_puts: append a NUL-terminated string to a buffer */ void hoedown_buffer_puts(hoedown_buffer *buf, const char *str); -/* hoedown_buffer_putc: appends a single char to a buffer */ +/* hoedown_buffer_putc: append a single char to a buffer */ void hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c); +/* hoedown_buffer_set: replace the buffer's contents with raw data */ +void hoedown_buffer_set(hoedown_buffer *buf, const uint8_t *data, size_t size); + +/* hoedown_buffer_sets: replace the buffer's contents with a NUL-terminated string */ +void hoedown_buffer_sets(hoedown_buffer *buf, const char *str); + +/* hoedown_buffer_eq: compare a buffer's data with other data for equality */ +int hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size); + +/* hoedown_buffer_eq: compare a buffer's data with NUL-terminated string for equality */ +int hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str); + /* hoedown_buffer_prefix: compare the beginning of a buffer with a string */ int hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix); -/* hoedown_buffer_slurp: removes a given number of bytes from the head of the array */ -void hoedown_buffer_slurp(hoedown_buffer *buf, size_t len); +/* hoedown_buffer_slurp: remove a given number of bytes from the head of the buffer */ +void hoedown_buffer_slurp(hoedown_buffer *buf, size_t size); /* hoedown_buffer_cstr: NUL-termination of the string array (making a C-string) */ const char *hoedown_buffer_cstr(hoedown_buffer *buf); @@ -84,6 +111,23 @@ const char *hoedown_buffer_cstr(hoedown_buffer *buf); /* hoedown_buffer_printf: formatted printing to a buffer */ void hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +/* hoedown_buffer_free: free the buffer */ +void hoedown_buffer_free(hoedown_buffer *buf); + + +/* HOEDOWN_BUFPUTSL: optimized hoedown_buffer_puts of a string literal */ +#define HOEDOWN_BUFPUTSL(output, literal) \ + hoedown_buffer_put(output, (const uint8_t *)literal, sizeof(literal) - 1) + +/* HOEDOWN_BUFSETSL: optimized hoedown_buffer_sets of a string literal */ +#define HOEDOWN_BUFSETSL(output, literal) \ + hoedown_buffer_set(output, (const uint8_t *)literal, sizeof(literal) - 1) + +/* HOEDOWN_BUFEQSL: optimized hoedown_buffer_eqs of a string literal */ +#define HOEDOWN_BUFEQSL(output, literal) \ + hoedown_buffer_eq(output, (const uint8_t *)literal, sizeof(literal) - 1) + + #ifdef __cplusplus } #endif diff --git a/src/document.c b/src/document.c index ba0e2f55..cf27290f 100644 --- a/src/document.c +++ b/src/document.c @@ -1,5 +1,3 @@ -/* document.c - generic markdown parser */ - #include "document.h" #include @@ -120,7 +118,7 @@ struct hoedown_document { struct footnote_list footnotes_used; uint8_t active_char[256]; hoedown_stack work_bufs[2]; - unsigned int ext_flags; + hoedown_extensions ext_flags; size_t max_nesting; int in_link_body; }; @@ -191,10 +189,7 @@ add_link_ref( struct link_ref **references, const uint8_t *name, size_t name_size) { - struct link_ref *ref = calloc(1, sizeof(struct link_ref)); - - if (!ref) - return NULL; + struct link_ref *ref = hoedown_calloc(1, sizeof(struct link_ref)); ref->id = hash_link_ref(name, name_size); ref->next = references[ref->id % REF_TABLE_SIZE]; @@ -243,9 +238,7 @@ free_link_refs(struct link_ref **references) static struct footnote_ref * create_footnote_ref(struct footnote_list *list, const uint8_t *name, size_t name_size) { - struct footnote_ref *ref = calloc(1, sizeof(struct footnote_ref)); - if (!ref) - return NULL; + struct footnote_ref *ref = hoedown_calloc(1, sizeof(struct footnote_ref)); ref->id = hash_link_ref(name, name_size); @@ -255,7 +248,7 @@ create_footnote_ref(struct footnote_list *list, const uint8_t *name, size_t name static int add_footnote_ref(struct footnote_list *list, struct footnote_ref *ref) { - struct footnote_item *item = calloc(1, sizeof(struct footnote_item)); + struct footnote_item *item = hoedown_calloc(1, sizeof(struct footnote_item)); if (!item) return 0; item->ref = ref; @@ -388,7 +381,7 @@ is_mail_autolink(uint8_t *data, size_t size) /* tag_length • returns the length of the given tag, or 0 is it's not valid */ static size_t -tag_length(uint8_t *data, size_t size, enum hoedown_autolink *autolink) +tag_length(uint8_t *data, size_t size, hoedown_autolink_type *autolink) { size_t i, j; @@ -453,8 +446,8 @@ static void parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) { size_t i = 0, end = 0; - uint8_t action = 0; hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL }; + uint8_t *active_char = doc->active_char; if (doc->work_bufs[BUFFER_SPAN].size + doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting) @@ -462,9 +455,8 @@ parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t si while (i < size) { /* copying inactive chars into the output */ - while (end < size && (action = doc->active_char[data[end]]) == 0) { + while (end < size && active_char[data[end]] == 0) end++; - } if (doc->md.normal_text) { work.data = data + i; @@ -477,7 +469,7 @@ parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t si if (end >= size) break; i = end; - end = markdown_char_ptrs[(int)action](ob, doc, data + i, i, size - i); + end = markdown_char_ptrs[ (int)active_char[data[end]] ](ob, doc, data + i, i, size - i); if (!end) /* no action from the callback */ end = i + 1; else { @@ -907,7 +899,7 @@ char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off static size_t char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) { - enum hoedown_autolink altype = HOEDOWN_AUTOLINK_NONE; + hoedown_autolink_type altype = HOEDOWN_AUTOLINK_NONE; size_t end = tag_length(data, size, &altype); hoedown_buffer work = { data, end, 0, 0, NULL, NULL, NULL }; int ret = 0; @@ -1744,7 +1736,7 @@ parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_listitem • parsing of a single list item */ /* assuming initial prefix is already removed */ static size_t -parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int *flags) +parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_listflags *flags) { hoedown_buffer *work = 0, *inter = 0; size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; @@ -1881,7 +1873,7 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_list • parsing ordered or unordered list block */ static size_t -parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int flags) +parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_listflags flags) { hoedown_buffer *work = 0; size_t i = 0, j; @@ -2044,7 +2036,7 @@ htmlblock_find_end_strict( while (i < size && data[i] != '\n') i++; if (i < size) i++; if (i == mark) return 0; - + if (data[mark] == ' ' && mark > 0) continue; mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark); if (mark == i && (is_empty(data + i, size - i) || i >= size)) break; @@ -2144,8 +2136,8 @@ parse_table_row( uint8_t *data, size_t size, size_t columns, - int *col_data, - int header_flag) + hoedown_tableflags *col_data, + hoedown_tableflags header_flag) { size_t i = 0, col; hoedown_buffer *row_work = 0; @@ -2201,7 +2193,7 @@ parse_table_header( uint8_t *data, size_t size, size_t *columns, - int **column_data) + hoedown_tableflags **column_data) { int pipes; size_t i = 0, col, header_end, under_end; @@ -2229,7 +2221,7 @@ parse_table_header( return 0; *columns = pipes + 1; - *column_data = calloc(*columns, sizeof(int)); + *column_data = hoedown_calloc(*columns, sizeof(hoedown_tableflags)); /* Parse the header underline */ i++; @@ -2299,7 +2291,7 @@ parse_table( hoedown_buffer *body_work = 0; size_t columns; - int *col_data = NULL; + hoedown_tableflags *col_data = NULL; header_work = newbuf(doc, BUFFER_SPAN); body_work = newbuf(doc, BUFFER_BLOCK); @@ -2489,7 +2481,7 @@ is_footnote(const uint8_t *data, size_t beg, size_t end, size_t *last, struct fo hoedown_buffer_put(contents, data + start + ind, i - start - ind); /* add carriage return */ if (i < end) { - hoedown_buffer_put(contents, "\n", 1); + hoedown_buffer_putc(contents, '\n'); if (i < end && (data[i] == '\n' || data[i] == '\r')) { i++; if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++; @@ -2662,21 +2654,18 @@ static void expand_tabs(hoedown_buffer *ob, const uint8_t *line, size_t size) hoedown_document * hoedown_document_new( const hoedown_renderer *renderer, - unsigned int extensions, + hoedown_extensions extensions, size_t max_nesting) { hoedown_document *doc = NULL; assert(max_nesting > 0 && renderer); - doc = malloc(sizeof(hoedown_document)); - if (!doc) - return NULL; - + doc = hoedown_malloc(sizeof(hoedown_document)); memcpy(&doc->md, renderer, sizeof(hoedown_renderer)); - hoedown_stack_new(&doc->work_bufs[BUFFER_BLOCK], 4); - hoedown_stack_new(&doc->work_bufs[BUFFER_SPAN], 8); + hoedown_stack_init(&doc->work_bufs[BUFFER_BLOCK], 4); + hoedown_stack_init(&doc->work_bufs[BUFFER_SPAN], 8); memset(doc->active_char, 0x0, 256); @@ -2723,7 +2712,7 @@ hoedown_document_new( } void -hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size) +hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size) { static const uint8_t UTF8_BOM[] = {0xEF, 0xBB, 0xBF}; @@ -2733,11 +2722,9 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t int footnotes_enabled; text = hoedown_buffer_new(64); - if (!text) - return; /* Preallocate enough space for our buffer to avoid expanding while copying */ - hoedown_buffer_grow(text, doc_size); + hoedown_buffer_grow(text, size); /* reset the references table */ memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *)); @@ -2755,26 +2742,26 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t /* Skip a possible UTF-8 BOM, even though the Unicode standard * discourages having these in UTF-8 documents */ - if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0) + if (size >= 3 && memcmp(data, UTF8_BOM, 3) == 0) beg += 3; - while (beg < doc_size) /* iterating over lines */ - if (footnotes_enabled && is_footnote(document, beg, doc_size, &end, &doc->footnotes_found)) + while (beg < size) /* iterating over lines */ + if (footnotes_enabled && is_footnote(data, beg, size, &end, &doc->footnotes_found)) beg = end; - else if (is_ref(document, beg, doc_size, &end, doc->refs)) + else if (is_ref(data, beg, size, &end, doc->refs)) beg = end; else { /* skipping to the next line */ end = beg; - while (end < doc_size && document[end] != '\n' && document[end] != '\r') + while (end < size && data[end] != '\n' && data[end] != '\r') end++; /* adding the line body if present */ if (end > beg) - expand_tabs(text, document + beg, end - beg); + expand_tabs(text, data + beg, end - beg); - while (end < doc_size && (document[end] == '\n' || document[end] == '\r')) { + while (end < size && (data[end] == '\n' || data[end] == '\r')) { /* add one \n per newline */ - if (document[end] == '\n' || (end + 1 < doc_size && document[end + 1] != '\n')) + if (data[end] == '\n' || (end + 1 < size && data[end + 1] != '\n')) hoedown_buffer_putc(text, '\n'); end++; } @@ -2817,38 +2804,36 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t } void -hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size) +hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size) { size_t i = 0, mark; hoedown_buffer *text = hoedown_buffer_new(64); - if (!text) - return; /* reset the references table */ memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *)); - /* first pass: convert all spacing to spaces */ - hoedown_buffer_grow(text, doc_size); + /* first pass: expand tabs and process newlines */ + hoedown_buffer_grow(text, size); while (1) { mark = i; - while (i < doc_size && document[i] != '\n' && document[i] != '\r') + while (i < size && data[i] != '\n' && data[i] != '\r') i++; - expand_tabs(text, document + mark, i - mark); + expand_tabs(text, data + mark, i - mark); - if (i >= doc_size) + if (i >= size) break; - while (i < doc_size && (document[i] == '\n' || document[i] == '\r')) { + while (i < size && (data[i] == '\n' || data[i] == '\r')) { /* add one \n per newline */ - if (document[i] == '\n' || (i + 1 < doc_size && document[i + 1] != '\n')) + if (data[i] == '\n' || (i + 1 < size && data[i + 1] != '\n')) hoedown_buffer_putc(text, '\n'); i++; } } /* second pass: actual rendering */ - hoedown_buffer_grow(ob, doc_size + (doc_size >> 1)); + hoedown_buffer_grow(ob, text->size + (text->size >> 1)); parse_inline(ob, doc, text->data, text->size); /* clean-up */ @@ -2869,8 +2854,8 @@ hoedown_document_free(hoedown_document *doc) for (i = 0; i < (size_t)doc->work_bufs[BUFFER_BLOCK].asize; ++i) hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]); - hoedown_stack_free(&doc->work_bufs[BUFFER_SPAN]); - hoedown_stack_free(&doc->work_bufs[BUFFER_BLOCK]); + hoedown_stack_reset(&doc->work_bufs[BUFFER_SPAN]); + hoedown_stack_reset(&doc->work_bufs[BUFFER_BLOCK]); free(doc); } diff --git a/src/document.h b/src/document.h index 8fec835b..539b206e 100644 --- a/src/document.h +++ b/src/document.h @@ -10,11 +10,12 @@ extern "C" { #endif -/********* - * FLAGS * - *********/ -enum hoedown_extensions { +/************* + * CONSTANTS * + *************/ + +typedef enum hoedown_extensions { /* block-level extensions */ HOEDOWN_EXT_TABLES = (1 << 0), HOEDOWN_EXT_FENCED_CODE = (1 << 1), @@ -35,7 +36,7 @@ enum hoedown_extensions { /* negative flags */ HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 12) -}; +} hoedown_extensions; #define HOEDOWN_EXT_BLOCK (\ HOEDOWN_EXT_TABLES |\ @@ -58,30 +59,29 @@ enum hoedown_extensions { #define HOEDOWN_EXT_NEGATIVE (\ HOEDOWN_EXT_DISABLE_INDENTED_CODE ) -/* list/listitem flags */ -enum hoedown_listflags { +typedef enum hoedown_listflags { HOEDOWN_LIST_ORDERED = (1 << 0), HOEDOWN_LI_BLOCK = (1 << 1) /*
  • containing block data */ -}; +} hoedown_listflags; -enum hoedown_tableflags { +typedef enum hoedown_tableflags { HOEDOWN_TABLE_ALIGN_LEFT = 1, HOEDOWN_TABLE_ALIGN_RIGHT = 2, HOEDOWN_TABLE_ALIGN_CENTER = 3, HOEDOWN_TABLE_ALIGNMASK = 3, HOEDOWN_TABLE_HEADER = 4 -}; +} hoedown_tableflags; -/* hoedown_autolink - type of autolink */ -enum hoedown_autolink { +typedef enum hoedown_autolink_type { HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/ HOEDOWN_AUTOLINK_NORMAL, /* normal http/http/ftp/mailto/etc link */ HOEDOWN_AUTOLINK_EMAIL /* e-mail link without explit mailto: */ -}; +} hoedown_autolink_type; -/******************** - * TYPE DEFINITIONS * - ********************/ + +/********* + * TYPES * + *********/ /* hoedown_renderer - functions for rendering parsed data */ struct hoedown_renderer { @@ -94,17 +94,17 @@ struct hoedown_renderer { void (*blockhtml)(hoedown_buffer *ob,const hoedown_buffer *text, void *opaque); void (*header)(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaque); void (*hrule)(hoedown_buffer *ob, void *opaque); - void (*list)(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque); - void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque); + void (*list)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_listflags flags, void *opaque); + void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_listflags flags, void *opaque); void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); void (*table)(hoedown_buffer *ob, const hoedown_buffer *header, const hoedown_buffer *body, void *opaque); void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); - void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque); + void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_tableflags flags, void *opaque); void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int num, void *opaque); /* span level callbacks - NULL or return 0 prints the span verbatim */ - int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, enum hoedown_autolink type, void *opaque); + int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, void *opaque); int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); @@ -128,31 +128,32 @@ struct hoedown_renderer { void (*doc_header)(hoedown_buffer *ob, void *opaque); void (*doc_footer)(hoedown_buffer *ob, void *opaque); }; - typedef struct hoedown_renderer hoedown_renderer; struct hoedown_document; - typedef struct hoedown_document hoedown_document; -/********************** - * EXPORTED FUNCTIONS * - **********************/ -extern hoedown_document * -hoedown_document_new( +/************* + * FUNCTIONS * + *************/ + +/* hoedown_document_new: allocate a new document processor instance */ +hoedown_document *hoedown_document_new( const hoedown_renderer *renderer, - unsigned int extensions, - size_t max_nesting); + hoedown_extensions extensions, + size_t max_nesting +) __attribute__ ((malloc)); + +/* hoedown_document_render: render regular Markdown using the document processor */ +void hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size); -extern void -hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size); +/* hoedown_document_render_inline: render inline Markdown using the document processor */ +void hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size); -extern void -hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size); +/* hoedown_document_free: deallocate a document processor instance */ +void hoedown_document_free(hoedown_document *doc); -extern void -hoedown_document_free(hoedown_document *doc); #ifdef __cplusplus } diff --git a/src/escape.c b/src/escape.c index 749eb75b..938d93cb 100644 --- a/src/escape.c +++ b/src/escape.c @@ -4,6 +4,11 @@ #include #include + +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) + + /* * The following characters will not be escaped: * @@ -17,7 +22,7 @@ * * We asume (lazily) that any RESERVED char that * appears inside an URL is actually meant to - * have its native function (i.e. as an URL + * have its native function (i.e. as an URL * component/separator) and hence needs no escaping. * * There are two exceptions: the chacters & (amp) @@ -30,58 +35,56 @@ * */ static const uint8_t HREF_SAFE[UINT8_MAX+1] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; void -hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size) +hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size) { static const char hex_chars[] = "0123456789ABCDEF"; - size_t i = 0, org; + size_t i = 0, mark; char hex_str[3]; hex_str[0] = '%'; while (i < size) { - org = i; - while (i < size && HREF_SAFE[src[i]] != 0) + mark = i; + while (i < size && HREF_SAFE[data[i]] != 0) i++; - if (i > org) { - if (org == 0) { - if (i >= size) { - hoedown_buffer_put(ob, src, size); - return; - } - - } + /* Optimization for cases when there's nothing to escape */ + if (mark == 0 && i >= size) { + hoedown_buffer_put(ob, data, size); + return; + } - hoedown_buffer_put(ob, src + org, i - org); + if (i > mark) { + hoedown_buffer_put(ob, data + mark, i - mark); } /* escaping */ if (i >= size) break; - switch (src[i]) { + switch (data[i]) { /* amp appears all the time in URLs, but needs * HTML-entity escaping to be inside an href */ - case '&': + case '&': HOEDOWN_BUFPUTSL(ob, "&"); break; @@ -91,7 +94,7 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size) case '\'': HOEDOWN_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 @@ -104,15 +107,16 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size) /* 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); + hex_str[1] = hex_chars[(data[i] >> 4) & 0xF]; + hex_str[2] = hex_chars[data[i] & 0xF]; + hoedown_buffer_put(ob, (uint8_t *)hex_str, 3); } i++; } } + /** * According to the OWASP rules: * @@ -125,21 +129,21 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size) * */ static const uint8_t HTML_ESCAPE_TABLE[UINT8_MAX+1] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; @@ -154,36 +158,30 @@ static const char *HTML_ESCAPES[] = { }; void -hoedown_escape_html(hoedown_buffer *ob, const uint8_t *src, size_t size, int secure) +hoedown_escape_html(hoedown_buffer *ob, const uint8_t *data, 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; - } + size_t i = 0, mark; - } + while (1) { + mark = i; + while (i < size && HTML_ESCAPE_TABLE[data[i]] == 0) i++; - hoedown_buffer_put(ob, src + org, i - org); + /* Optimization for cases where there's nothing to escape */ + if (mark == 0 && i >= size) { + hoedown_buffer_put(ob, data, size); + return; } - /* escaping */ - if (i >= size) - break; + if (likely(i > mark)) + hoedown_buffer_put(ob, data + mark, i - mark); + + if (i >= size) break; /* The forward slash is only escaped in secure mode */ - if (src[i] == '/' && !secure) { + if (!secure && data[i] == '/') { hoedown_buffer_putc(ob, '/'); } else { - hoedown_buffer_puts(ob, HTML_ESCAPES[esc]); + hoedown_buffer_puts(ob, HTML_ESCAPES[HTML_ESCAPE_TABLE[data[i]]]); } i++; diff --git a/src/escape.h b/src/escape.h index 95be8603..d7659c27 100644 --- a/src/escape.h +++ b/src/escape.h @@ -9,8 +9,17 @@ extern "C" { #endif -extern void hoedown_escape_html(hoedown_buffer *ob, const uint8_t *src, size_t size, int secure); -extern void hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size); + +/************* + * FUNCTIONS * + *************/ + +/* hoedown_escape_href: escape (part of) a URL inside HTML */ +void hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size); + +/* hoedown_escape_html: escape HTML */ +void hoedown_escape_html(hoedown_buffer *ob, const uint8_t *data, size_t size, int secure); + #ifdef __cplusplus } diff --git a/src/html.c b/src/html.c index 8059b0c5..7bc8ff90 100644 --- a/src/html.c +++ b/src/html.c @@ -9,34 +9,34 @@ #define USE_XHTML(opt) (opt->flags & HOEDOWN_HTML_USE_XHTML) -int -hoedown_html_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname) +hoedown_html_tag +hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname) { size_t i; int closed = 0; - if (tag_size < 3 || tag_data[0] != '<') + if (size < 3 || data[0] != '<') return HOEDOWN_HTML_TAG_NONE; i = 1; - if (tag_data[i] == '/') { + if (data[i] == '/') { closed = 1; i++; } - for (; i < tag_size; ++i, ++tagname) { + for (; i < size; ++i, ++tagname) { if (*tagname == 0) break; - if (tag_data[i] != *tagname) + if (data[i] != *tagname) return HOEDOWN_HTML_TAG_NONE; } - if (i == tag_size) + if (i == size) return HOEDOWN_HTML_TAG_NONE; - if (isspace(tag_data[i]) || tag_data[i] == '>') + if (isspace(data[i]) || data[i] == '>') return closed ? HOEDOWN_HTML_TAG_CLOSE : HOEDOWN_HTML_TAG_OPEN; return HOEDOWN_HTML_TAG_NONE; @@ -56,7 +56,7 @@ static inline void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t * GENERIC RENDERER * ********************/ static int -rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, enum hoedown_autolink type, void *opaque) +rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, void *opaque) { hoedown_html_renderer_state *state = opaque; @@ -268,9 +268,9 @@ static void rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque) { if (ob->size) hoedown_buffer_putc(ob, '\n'); - hoedown_buffer_put(ob, flags & HOEDOWN_LIST_ORDERED ? "
      \n" : "
        \n", 5); + hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
          \n" : "
            \n"), 5); if (text) hoedown_buffer_put(ob, text->data, text->size); - hoedown_buffer_put(ob, flags & HOEDOWN_LIST_ORDERED ? "
        \n" : "
      \n", 6); + hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
    \n" : "\n"), 6); } static void @@ -428,7 +428,7 @@ rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque) } static void -rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque) +rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_tableflags flags, void *opaque) { if (flags & HOEDOWN_TABLE_HEADER) { HOEDOWN_BUFPUTSL(ob, "\n"); hoedown_buffer_puts(ob, USE_XHTML(state) ? "
    \n" : "
    \n"); HOEDOWN_BUFPUTSL(ob, "
      \n"); - + if (text) hoedown_buffer_put(ob, text->data, text->size); - + HOEDOWN_BUFPUTSL(ob, "\n
    \n\n"); } @@ -501,7 +501,7 @@ rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int n { size_t i = 0; int pfound = 0; - + /* insert anchor at the end of first paragraph block */ if (text) { while ((i+3) < text->size) { @@ -514,7 +514,7 @@ rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int n break; } } - + hoedown_buffer_printf(ob, "\n
  • \n", num); if (pfound) { hoedown_buffer_put(ob, text->data, i); @@ -634,23 +634,15 @@ hoedown_html_toc_renderer_new(int nesting_level) hoedown_renderer *renderer; /* Prepare the state pointer */ - state = malloc(sizeof(hoedown_html_renderer_state)); - if (!state) - return NULL; - + state = hoedown_malloc(sizeof(hoedown_html_renderer_state)); memset(state, 0x0, sizeof(hoedown_html_renderer_state)); state->toc_data.nesting_level = nesting_level; /* Prepare the renderer */ - renderer = malloc(sizeof(hoedown_renderer)); - if (!renderer) { - free(state); - return NULL; - } - + renderer = hoedown_malloc(sizeof(hoedown_renderer)); memcpy(renderer, &cb_default, sizeof(hoedown_renderer)); - + renderer->opaque = state; return renderer; } @@ -658,7 +650,7 @@ hoedown_html_toc_renderer_new(int nesting_level) hoedown_renderer * hoedown_html_renderer_new(unsigned int render_flags, int nesting_level) { - static const hoedown_renderer cb_default = { + static const hoedown_renderer cb_default = { NULL, rndr_blockcode, @@ -702,27 +694,19 @@ hoedown_html_renderer_new(unsigned int render_flags, int nesting_level) hoedown_renderer *renderer; /* Prepare the state pointer */ - state = malloc(sizeof(hoedown_html_renderer_state)); - if (!state) - return NULL; - + state = hoedown_malloc(sizeof(hoedown_html_renderer_state)); memset(state, 0x0, sizeof(hoedown_html_renderer_state)); state->flags = render_flags; state->toc_data.nesting_level = nesting_level; /* Prepare the renderer */ - renderer = malloc(sizeof(hoedown_renderer)); - if (!renderer) { - free(state); - return NULL; - } - + renderer = hoedown_malloc(sizeof(hoedown_renderer)); memcpy(renderer, &cb_default, sizeof(hoedown_renderer)); if (render_flags & HOEDOWN_HTML_SKIP_HTML || render_flags & HOEDOWN_HTML_ESCAPE) renderer->blockhtml = NULL; - + renderer->opaque = state; return renderer; } diff --git a/src/html.h b/src/html.h index 46b424be..8e321d82 100644 --- a/src/html.h +++ b/src/html.h @@ -1,17 +1,21 @@ -/* html.h - HTML renderer */ +/* html.h - HTML renderer and utilities */ #ifndef HOEDOWN_HTML_H #define HOEDOWN_HTML_H #include "document.h" #include "buffer.h" -#include #ifdef __cplusplus extern "C" { #endif -typedef enum { + +/************* + * CONSTANTS * + *************/ + +typedef enum hoedown_html_flags { HOEDOWN_HTML_SKIP_HTML = (1 << 0), HOEDOWN_HTML_ESCAPE = (1 << 1), HOEDOWN_HTML_SAFELINK = (1 << 2), @@ -19,12 +23,17 @@ typedef enum { HOEDOWN_HTML_USE_XHTML = (1 << 4) } hoedown_html_flags; -typedef enum { +typedef enum hoedown_html_tag { HOEDOWN_HTML_TAG_NONE = 0, HOEDOWN_HTML_TAG_OPEN, HOEDOWN_HTML_TAG_CLOSE } hoedown_html_tag; + +/********* + * TYPES * + *********/ + struct hoedown_html_renderer_state { void *opaque; @@ -35,28 +44,39 @@ struct hoedown_html_renderer_state { int nesting_level; } toc_data; - unsigned int flags; + hoedown_html_flags flags; /* extra callbacks */ void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, void *self); }; - typedef struct hoedown_html_renderer_state hoedown_html_renderer_state; -int -hoedown_html_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname); -extern hoedown_renderer * -hoedown_html_renderer_new(unsigned int render_flags, int nesting_level); +/************* + * FUNCTIONS * + *************/ + +/* hoedown_html_smartypants: process an HTML snippet using SmartyPants for smart punctuation */ +void hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *data, size_t size); + +/* hoedown_html_is_tag: checks if data starts with a specific tag, returns the tag type or NONE */ +hoedown_html_tag hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname); + + +/* hoedown_html_renderer_new: allocates a regular HTML renderer */ +hoedown_renderer *hoedown_html_renderer_new( + hoedown_html_flags render_flags, + int nesting_level +) __attribute__ ((malloc)); -extern hoedown_renderer * -hoedown_html_toc_renderer_new(int nesting_level); +/* hoedown_html_toc_renderer_new: like hoedown_html_renderer_new, but the returned renderer produces the Table of Contents */ +hoedown_renderer *hoedown_html_toc_renderer_new( + int nesting_level +) __attribute__ ((malloc)); -extern void -hoedown_html_renderer_free(hoedown_renderer *renderer); +/* hoedown_html_renderer_free: deallocate an HTML renderer */ +void hoedown_html_renderer_free(hoedown_renderer *renderer); -extern void -hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *text, size_t size); #ifdef __cplusplus } diff --git a/src/stack.c b/src/stack.c index d0dea29a..22a7ae1a 100644 --- a/src/stack.c +++ b/src/stack.c @@ -1,25 +1,29 @@ #include "stack.h" +#include "buffer.h" + +#include #include +#include -int -hoedown_stack_new(hoedown_stack *st, size_t initial_size) +void +hoedown_stack_init(hoedown_stack *st, size_t initial_size) { + assert(st); + st->item = NULL; - st->size = 0; - st->asize = 0; + st->size = st->asize = 0; if (!initial_size) initial_size = 8; - return hoedown_stack_grow(st, initial_size); + hoedown_stack_grow(st, initial_size); } void -hoedown_stack_free(hoedown_stack *st) +hoedown_stack_reset(hoedown_stack *st) { - if (!st) - return; + assert(st); free(st->item); @@ -28,43 +32,38 @@ hoedown_stack_free(hoedown_stack *st) st->asize = 0; } -int -hoedown_stack_grow(hoedown_stack *st, size_t new_size) +void +hoedown_stack_grow(hoedown_stack *st, size_t neosz) { - void **new_st; - - if (st->asize >= new_size) - return 0; + assert(st); - new_st = realloc(st->item, new_size * sizeof(void *)); - if (new_st == NULL) - return -1; - - memset(new_st + st->asize, 0x0, - (new_size - st->asize) * sizeof(void *)); - - st->item = new_st; - st->asize = new_size; + if (st->asize >= neosz) + return; - if (st->size > new_size) - st->size = new_size; + st->item = hoedown_realloc(st->item, neosz * sizeof(void *)); + memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *)); + st->asize = neosz; - return 0; + if (st->size > neosz) + st->size = neosz; } -int +void hoedown_stack_push(hoedown_stack *st, void *item) { - if (hoedown_stack_grow(st, st->size * 2) < 0) - return -1; + assert(st); + + if (st->size >= st->asize) + hoedown_stack_grow(st, (st->size + 1) * 2); st->item[st->size++] = item; - return 0; } void * hoedown_stack_pop(hoedown_stack *st) { + assert(st); + if (!st->size) return NULL; @@ -72,8 +71,10 @@ hoedown_stack_pop(hoedown_stack *st) } void * -hoedown_stack_top(hoedown_stack *st) +hoedown_stack_top(const hoedown_stack *st) { + assert(st); + if (!st->size) return NULL; diff --git a/src/stack.h b/src/stack.h index 9063592b..a0f09c61 100644 --- a/src/stack.h +++ b/src/stack.h @@ -3,26 +3,47 @@ #ifndef HOEDOWN_STACK_H #define HOEDOWN_STACK_H -#include +#include #ifdef __cplusplus extern "C" { #endif + +/********* + * TYPES * + *********/ + struct hoedown_stack { void **item; size_t size; size_t asize; }; - typedef struct hoedown_stack hoedown_stack; -int hoedown_stack_new(hoedown_stack *, size_t); -void hoedown_stack_free(hoedown_stack *); -int hoedown_stack_grow(hoedown_stack *, size_t); -int hoedown_stack_push(hoedown_stack *, void *); -void *hoedown_stack_pop(hoedown_stack *); -void *hoedown_stack_top(hoedown_stack *); + +/************* + * FUNCTIONS * + *************/ + +/* hoedown_stack_init: initialize a stack */ +void hoedown_stack_init(hoedown_stack *st, size_t initial_size); + +/* hoedown_stack_reset: free internal data of the stack */ +void hoedown_stack_reset(hoedown_stack *st); + +/* hoedown_stack_grow: increase the allocated size to the given value */ +void hoedown_stack_grow(hoedown_stack *st, size_t neosz); + +/* hoedown_stack_push: push an item to the top of the stack */ +void hoedown_stack_push(hoedown_stack *st, void *item); + +/* hoedown_stack_pop: retrieve and remove the item at the top of the stack */ +void *hoedown_stack_pop(hoedown_stack *st); + +/* hoedown_stack_top: retrieve the item at the top of the stack */ +void *hoedown_stack_top(const hoedown_stack *st); + #ifdef __cplusplus } diff --git a/src/version.h b/src/version.h index 39716582..9b30f1d7 100644 --- a/src/version.h +++ b/src/version.h @@ -7,13 +7,24 @@ extern "C" { #endif + +/************* + * CONSTANTS * + *************/ + #define HOEDOWN_VERSION "2.0.0" #define HOEDOWN_VERSION_MAJOR 2 #define HOEDOWN_VERSION_MINOR 0 #define HOEDOWN_VERSION_REVISION 0 -extern void -hoedown_version(int *major, int *minor, int *revision); + +/************* + * FUNCTIONS * + *************/ + +/* hoedown_version: retrieve Hoedown's version numbers */ +void hoedown_version(int *major, int *minor, int *revision); + #ifdef __cplusplus } From 73d8a1120a6e0515801757076995ea0496b17850 Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Wed, 3 Sep 2014 10:39:33 +0200 Subject: [PATCH 02/17] More fixes --- hoedown.def | 24 +++++++++++++++--------- src/document.c | 18 +++++++++--------- src/document.h | 14 +++++++------- src/escape.c | 7 +++---- src/html.c | 8 ++++---- src/stack.c | 9 +++------ src/stack.h | 4 ++-- src/version.c | 8 ++++---- 8 files changed, 47 insertions(+), 45 deletions(-) diff --git a/hoedown.def b/hoedown.def index 09b54a7d..3b2c69ff 100644 --- a/hoedown.def +++ b/hoedown.def @@ -4,30 +4,36 @@ EXPORTS hoedown_autolink__www hoedown_autolink__email hoedown_autolink__url - hoedown_buffer_grow + hoedown_buffer_init hoedown_buffer_new - hoedown_buffer_cstr - hoedown_buffer_prefix + hoedown_buffer_reset + hoedown_buffer_grow hoedown_buffer_put hoedown_buffer_puts hoedown_buffer_putc - hoedown_buffer_free - hoedown_buffer_reset + hoedown_buffer_set + hoedown_buffer_sets + hoedown_buffer_eq + hoedown_buffer_eqs + hoedown_buffer_prefix hoedown_buffer_slurp + hoedown_buffer_cstr hoedown_buffer_printf + hoedown_buffer_free hoedown_document_new hoedown_document_render + hoedown_document_render_inline hoedown_document_free - hoedown_escape_html hoedown_escape_href + hoedown_escape_html + hoedown_html_smartypants hoedown_html_is_tag hoedown_html_renderer_new hoedown_html_toc_renderer_new hoedown_html_renderer_free - hoedown_html_smartypants - hoedown_stack_free + hoedown_stack_init + hoedown_stack_uninit hoedown_stack_grow - hoedown_stack_new hoedown_stack_push hoedown_stack_pop hoedown_stack_top diff --git a/src/document.c b/src/document.c index cf27290f..c0e52efb 100644 --- a/src/document.c +++ b/src/document.c @@ -1736,7 +1736,7 @@ parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_listitem • parsing of a single list item */ /* assuming initial prefix is already removed */ static size_t -parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_listflags *flags) +parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags *flags) { hoedown_buffer *work = 0, *inter = 0; size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; @@ -1873,7 +1873,7 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_list • parsing ordered or unordered list block */ static size_t -parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_listflags flags) +parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags flags) { hoedown_buffer *work = 0; size_t i = 0, j; @@ -2136,8 +2136,8 @@ parse_table_row( uint8_t *data, size_t size, size_t columns, - hoedown_tableflags *col_data, - hoedown_tableflags header_flag) + hoedown_table_flags *col_data, + hoedown_table_flags header_flag) { size_t i = 0, col; hoedown_buffer *row_work = 0; @@ -2193,7 +2193,7 @@ parse_table_header( uint8_t *data, size_t size, size_t *columns, - hoedown_tableflags **column_data) + hoedown_table_flags **column_data) { int pipes; size_t i = 0, col, header_end, under_end; @@ -2221,7 +2221,7 @@ parse_table_header( return 0; *columns = pipes + 1; - *column_data = hoedown_calloc(*columns, sizeof(hoedown_tableflags)); + *column_data = hoedown_calloc(*columns, sizeof(hoedown_table_flags)); /* Parse the header underline */ i++; @@ -2291,7 +2291,7 @@ parse_table( hoedown_buffer *body_work = 0; size_t columns; - hoedown_tableflags *col_data = NULL; + hoedown_table_flags *col_data = NULL; header_work = newbuf(doc, BUFFER_SPAN); body_work = newbuf(doc, BUFFER_BLOCK); @@ -2854,8 +2854,8 @@ hoedown_document_free(hoedown_document *doc) for (i = 0; i < (size_t)doc->work_bufs[BUFFER_BLOCK].asize; ++i) hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]); - hoedown_stack_reset(&doc->work_bufs[BUFFER_SPAN]); - hoedown_stack_reset(&doc->work_bufs[BUFFER_BLOCK]); + hoedown_stack_uninit(&doc->work_bufs[BUFFER_SPAN]); + hoedown_stack_uninit(&doc->work_bufs[BUFFER_BLOCK]); free(doc); } diff --git a/src/document.h b/src/document.h index 539b206e..9564f382 100644 --- a/src/document.h +++ b/src/document.h @@ -59,18 +59,18 @@ typedef enum hoedown_extensions { #define HOEDOWN_EXT_NEGATIVE (\ HOEDOWN_EXT_DISABLE_INDENTED_CODE ) -typedef enum hoedown_listflags { +typedef enum hoedown_list_flags { HOEDOWN_LIST_ORDERED = (1 << 0), HOEDOWN_LI_BLOCK = (1 << 1) /*
  • containing block data */ -} hoedown_listflags; +} hoedown_list_flags; -typedef enum hoedown_tableflags { +typedef enum hoedown_table_flags { HOEDOWN_TABLE_ALIGN_LEFT = 1, HOEDOWN_TABLE_ALIGN_RIGHT = 2, HOEDOWN_TABLE_ALIGN_CENTER = 3, HOEDOWN_TABLE_ALIGNMASK = 3, HOEDOWN_TABLE_HEADER = 4 -} hoedown_tableflags; +} hoedown_table_flags; typedef enum hoedown_autolink_type { HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/ @@ -94,12 +94,12 @@ struct hoedown_renderer { void (*blockhtml)(hoedown_buffer *ob,const hoedown_buffer *text, void *opaque); void (*header)(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaque); void (*hrule)(hoedown_buffer *ob, void *opaque); - void (*list)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_listflags flags, void *opaque); - void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_listflags flags, void *opaque); + void (*list)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque); + void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque); void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); void (*table)(hoedown_buffer *ob, const hoedown_buffer *header, const hoedown_buffer *body, void *opaque); void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); - void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_tableflags flags, void *opaque); + void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_table_flags flags, void *opaque); void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int num, void *opaque); diff --git a/src/escape.c b/src/escape.c index 938d93cb..b4ec911f 100644 --- a/src/escape.c +++ b/src/escape.c @@ -64,16 +64,15 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size) while (i < size) { mark = i; - while (i < size && HREF_SAFE[data[i]] != 0) - i++; + while (i < size && HREF_SAFE[data[i]]) i++; - /* Optimization for cases when there's nothing to escape */ + /* Optimization for cases where there's nothing to escape */ if (mark == 0 && i >= size) { hoedown_buffer_put(ob, data, size); return; } - if (i > mark) { + if (likely(i > mark)) { hoedown_buffer_put(ob, data + mark, i - mark); } diff --git a/src/html.c b/src/html.c index 7bc8ff90..03c85007 100644 --- a/src/html.c +++ b/src/html.c @@ -265,7 +265,7 @@ rndr_link(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer * } static void -rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque) +rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque) { if (ob->size) hoedown_buffer_putc(ob, '\n'); hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
      \n" : "
        \n"), 5); @@ -274,7 +274,7 @@ rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, vo } static void -rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque) +rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque) { HOEDOWN_BUFPUTSL(ob, "
      • "); if (text) { @@ -428,7 +428,7 @@ rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque) } static void -rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_tableflags flags, void *opaque) +rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_table_flags flags, void *opaque) { if (flags & HOEDOWN_TABLE_HEADER) { HOEDOWN_BUFPUTSL(ob, "item); - - st->item = NULL; - st->size = 0; - st->asize = 0; } void @@ -42,6 +38,7 @@ hoedown_stack_grow(hoedown_stack *st, size_t neosz) st->item = hoedown_realloc(st->item, neosz * sizeof(void *)); memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *)); + st->asize = neosz; if (st->size > neosz) @@ -54,7 +51,7 @@ hoedown_stack_push(hoedown_stack *st, void *item) assert(st); if (st->size >= st->asize) - hoedown_stack_grow(st, (st->size + 1) * 2); + hoedown_stack_grow(st, st->size * 2); st->item[st->size++] = item; } diff --git a/src/stack.h b/src/stack.h index a0f09c61..bf9b439b 100644 --- a/src/stack.h +++ b/src/stack.h @@ -29,8 +29,8 @@ typedef struct hoedown_stack hoedown_stack; /* hoedown_stack_init: initialize a stack */ void hoedown_stack_init(hoedown_stack *st, size_t initial_size); -/* hoedown_stack_reset: free internal data of the stack */ -void hoedown_stack_reset(hoedown_stack *st); +/* hoedown_stack_uninit: free internal data of the stack */ +void hoedown_stack_uninit(hoedown_stack *st); /* hoedown_stack_grow: increase the allocated size to the given value */ void hoedown_stack_grow(hoedown_stack *st, size_t neosz); diff --git a/src/version.c b/src/version.c index 73a70bcc..744209b8 100644 --- a/src/version.c +++ b/src/version.c @@ -1,9 +1,9 @@ #include "version.h" void -hoedown_version(int *ver_major, int *ver_minor, int *ver_revision) +hoedown_version(int *major, int *minor, int *revision) { - *ver_major = HOEDOWN_VERSION_MAJOR; - *ver_minor = HOEDOWN_VERSION_MINOR; - *ver_revision = HOEDOWN_VERSION_REVISION; + *major = HOEDOWN_VERSION_MAJOR; + *minor = HOEDOWN_VERSION_MINOR; + *revision = HOEDOWN_VERSION_REVISION; } From a715656fb736b9c1cd02e48da1b6c7bc56a0315f Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Wed, 3 Sep 2014 11:14:58 +0200 Subject: [PATCH 03/17] Add __builtin_expect fallback for MSVC --- src/buffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/buffer.h b/src/buffer.h index 5cc074d4..6d42385d 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -16,6 +16,7 @@ extern "C" { #if defined(_MSC_VER) #define __attribute__(x) #define inline __inline +#define __builtin_expect(x,n) x #endif From 30dd50f16a27d1aa649c188d57a09920b21ceba3 Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Thu, 4 Sep 2014 14:17:50 +0200 Subject: [PATCH 04/17] Keep code without warnings --- src/document.h | 12 ++++++------ src/html.c | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/document.h b/src/document.h index 98b957af..e586ef2e 100644 --- a/src/document.h +++ b/src/document.h @@ -28,16 +28,16 @@ typedef enum hoedown_extensions { HOEDOWN_EXT_HIGHLIGHT = (1 << 6), HOEDOWN_EXT_QUOTE = (1 << 7), HOEDOWN_EXT_SUPERSCRIPT = (1 << 8), - HOEDOWN_EXT_MATH = (1 << 13), + HOEDOWN_EXT_MATH = (1 << 9), /* other flags */ - HOEDOWN_EXT_LAX_SPACING = (1 << 9), - HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 10), - HOEDOWN_EXT_SPACE_HEADERS = (1 << 11), - HOEDOWN_EXT_MATH_EXPLICIT = (1 << 14), + HOEDOWN_EXT_LAX_SPACING = (1 << 10), + HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11), + HOEDOWN_EXT_SPACE_HEADERS = (1 << 12), + HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13), /* negative flags */ - HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 12) + HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14) } hoedown_extensions; #define HOEDOWN_EXT_BLOCK (\ diff --git a/src/html.c b/src/html.c index 92156f69..231b8b7f 100644 --- a/src/html.c +++ b/src/html.c @@ -268,9 +268,9 @@ static void rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque) { if (ob->size) hoedown_buffer_putc(ob, '\n'); - hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
          \n" : "
            \n"), 5); + hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
              \n" : "
                \n"), 5); if (text) hoedown_buffer_put(ob, text->data, text->size); - hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
            \n" : "
          \n"), 6); + hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "
        \n" : "
      \n"), 6); } static void @@ -536,9 +536,9 @@ rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, void *opaque) static int rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, void *opaque) { - hoedown_buffer_put(ob, displaymode ? "\\[" : "\\(", 2); + hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\[" : "\\("), 2); escape_html(ob, text->data, text->size); - hoedown_buffer_put(ob, displaymode ? "\\]" : "\\)", 2); + hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\]" : "\\)"), 2); return 1; } From 8cc788ec597b8ca1d1b7e8249fd0072ae3034124 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 16:10:50 +0800 Subject: [PATCH 05/17] New Python implemented test script --- Makefile | 2 +- .../Tests/Escape character.html | 0 .../Tests/Escape character.text | 0 test/config.json | 97 +++++++++++++++++++ test/runner.py | 94 ++++++++++++++++++ test/runner.sh | 50 ---------- 6 files changed, 192 insertions(+), 51 deletions(-) rename test/{MarkdownTest_1.0.3 => }/Tests/Escape character.html (100%) rename test/{MarkdownTest_1.0.3 => }/Tests/Escape character.text (100%) create mode 100644 test/config.json create mode 100755 test/runner.py delete mode 100755 test/runner.sh diff --git a/Makefile b/Makefile index 998a41d4..66ead31c 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ src/html_blocks.c: html_block_names.gperf # Testing test: hoedown - test/runner.sh ./hoedown test/MarkdownTest_1.0.3/Tests + test/runner.py test-pl: hoedown perl test/MarkdownTest_1.0.3/MarkdownTest.pl \ diff --git a/test/MarkdownTest_1.0.3/Tests/Escape character.html b/test/Tests/Escape character.html similarity index 100% rename from test/MarkdownTest_1.0.3/Tests/Escape character.html rename to test/Tests/Escape character.html diff --git a/test/MarkdownTest_1.0.3/Tests/Escape character.text b/test/Tests/Escape character.text similarity index 100% rename from test/MarkdownTest_1.0.3/Tests/Escape character.text rename to test/Tests/Escape character.text diff --git a/test/config.json b/test/config.json new file mode 100644 index 00000000..cec160c6 --- /dev/null +++ b/test/config.json @@ -0,0 +1,97 @@ +{ + "tests": [ + { + "input": "MarkdownTest_1.0.3/Tests/Amps and angle encoding.text", + "output": "MarkdownTest_1.0.3/Tests/Amps and angle encoding.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Auto links.text", + "output": "MarkdownTest_1.0.3/Tests/Auto links.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Backslash escapes.text", + "output": "MarkdownTest_1.0.3/Tests/Backslash escapes.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text", + "output": "MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Code Blocks.text", + "output": "MarkdownTest_1.0.3/Tests/Code Blocks.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Code Spans.text", + "output": "MarkdownTest_1.0.3/Tests/Code Spans.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text", + "output": "MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Horizontal rules.text", + "output": "MarkdownTest_1.0.3/Tests/Horizontal rules.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text", + "output": "MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text", + "output": "MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Inline HTML comments.text", + "output": "MarkdownTest_1.0.3/Tests/Inline HTML comments.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Links, inline style.text", + "output": "MarkdownTest_1.0.3/Tests/Links, inline style.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Links, reference style.text", + "output": "MarkdownTest_1.0.3/Tests/Links, reference style.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Links, shortcut references.text", + "output": "MarkdownTest_1.0.3/Tests/Links, shortcut references.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Literal quotes in titles.text", + "output": "MarkdownTest_1.0.3/Tests/Literal quotes in titles.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text", + "output": "MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text", + "output": "MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Nested blockquotes.text", + "output": "MarkdownTest_1.0.3/Tests/Nested blockquotes.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text", + "output": "MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Strong and em together.text", + "output": "MarkdownTest_1.0.3/Tests/Strong and em together.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Tabs.text", + "output": "MarkdownTest_1.0.3/Tests/Tabs.html" + }, + { + "input": "MarkdownTest_1.0.3/Tests/Tidyness.text", + "output": "MarkdownTest_1.0.3/Tests/Tidyness.html" + }, + { + "input": "Tests/Escape character.text", + "output": "Tests/Escape character.html", + "skip": true + } + ] +} diff --git a/test/runner.py b/test/runner.py new file mode 100755 index 00000000..5ebd78fe --- /dev/null +++ b/test/runner.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals, print_function +import os +import sys +import copy +import json +import re +import subprocess +import unittest + +DLN = '======================================================================' +SLN = '----------------------------------------------------------------------' +TEST_ROOT = os.path.dirname(__file__) +HOEDOWN = [os.path.join(os.path.dirname(TEST_ROOT), 'hoedown')] +TIDY = ['tidy', '--show-body-only', '1', '--show-warnings', '0', + '--quiet', '1'] +CONFIG_PATH = os.path.join(TEST_ROOT, 'config.json') +SLUGIFY_PATTERN = re.compile(r'\W') + + +class TestFailed(AssertionError): + def __init__(self, name, expected, got): + super(TestFailed, self).__init__(self) + description_format = ( + '{name}\nExpected\n{sln}\n{expected}\n\n' + 'Got\n{sln}\n{got}\n\n' + ) + self.description = description_format.format( + dln=DLN, sln=SLN, name=name, + expected=expected.strip(), got=got.strip(), + ) + + def __str__(self): + return self.description + + +def _test_func(test_case): + flags = test_case.get('flags') or [] + hoedown_proc = subprocess.Popen( + HOEDOWN + flags + [os.path.join(TEST_ROOT, test_case['input'])], + stdout=subprocess.PIPE, + ) + hoedown_proc.wait() + got_tidy_proc = subprocess.Popen( + TIDY, stdin=hoedown_proc.stdout, stdout=subprocess.PIPE, + ) + got_tidy_proc.wait() + got = got_tidy_proc.stdout.read() + + expected_tidy_proc = subprocess.Popen( + TIDY + [os.path.join(TEST_ROOT, test_case['output'])], + stdout=subprocess.PIPE, + ) + expected_tidy_proc.wait() + expected = expected_tidy_proc.stdout.read() + + try: + assert expected == got + except AssertionError: + raise TestFailed(test_case['input'], expected, got) + + +def _make_test(test_case): + return lambda self: _test_func(test_case) + + +class MarkdownTestCaseMeta(type): + """Meta class for ``MarkdownTestCase`` to inject test cases on the fly. + """ + def __new__(meta, name, bases, attrs): + with open(CONFIG_PATH) as f: + config = json.load(f) + + for test in config['tests']: + input_name = test['input'] + attr_name = 'test_' + SLUGIFY_PATTERN.sub( + '_', os.path.splitext(input_name)[0].lower(), + ) + func = _make_test(test) + func.__doc__ = input_name + if test.get('skip', False): + func = unittest.skip(input_name)(func) + attrs[attr_name] = func + return type.__new__(meta, name, bases, attrs) + + +class MarkdownTestCase(unittest.TestCase): + __metaclass__ = MarkdownTestCaseMeta + + +if __name__ == '__main__': + unittest.main() diff --git a/test/runner.sh b/test/runner.sh deleted file mode 100755 index d60eac56..00000000 --- a/test/runner.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -POSIXLY_CORRECT=1 -export POSIXLY_CORRECT - -TIDY='tidy --show-body-only 1 --quiet 1 --show-warnings 0' -SCRIPT="$1" -TESTDIR="$2" -PASSED=0 -FAILED=0 - -abort() { - echo "Error: $*" - exit 1 -} - -test -f "$SCRIPT" || abort "argument #1 invalid; not a file" -test -x "$SCRIPT" || abort "argument #1 invalid; not executable" -echo "" | "$SCRIPT" || abort "argument #1 invalid; script failed to run" -test -d "$TESTDIR" || abort "argument #2 invalid; not a directory" - -for TEXT in "$TESTDIR"/*.text; do - test -f "$TEXT" || abort "empty or invalid test directory" - printf "$(basename "$TEXT" .text) ... " - HTML=$(echo "$TEXT" | sed 's/\.text$/.html/') - - # We use mktemp to create an unpredictable, temporary filename. - # The created file is immediately deleted, since we only want a - # name to pass to mkfifo and "mktemp -u" is not portable. - PIPE=$(mktemp .testpipe-XXXXXXXX) - test -f "$PIPE" -a -n "$PIPE" || abort "mktemp failed" - trap 'rm -f "$PIPE"' EXIT INT TERM HUP - rm -f "$PIPE" - mkfifo -m 0600 "$PIPE" || abort "unable to create named pipe" - - $SCRIPT "$TEXT" | $TIDY > "$PIPE" & - DIFF=$($TIDY "$HTML" | diff "$PIPE" -) - if test "$?" = 0; then - PASSED=$(expr $PASSED + 1) - echo OK - else - FAILED=$(expr $FAILED + 1) - echo FAILED - printf "\n$DIFF\n\n" - fi - rm -f "$PIPE" -done - -printf "\n\n$PASSED passed; $FAILED failed.\n" -test "$FAILED" = 0 || exit 1 From b49d385be355e08536974e98e8644609319e596f Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 16:30:01 +0800 Subject: [PATCH 06/17] Add math test (modified) and tweak runner --- test/Tests/Math.html | 31 +++++++++++++++++++++++++++++++ test/Tests/Math.text | 31 +++++++++++++++++++++++++++++++ test/config.json | 5 +++++ test/runner.py | 9 +++++---- 4 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 test/Tests/Math.html create mode 100644 test/Tests/Math.text diff --git a/test/Tests/Math.html b/test/Tests/Math.html new file mode 100644 index 00000000..5e2fd3eb --- /dev/null +++ b/test/Tests/Math.html @@ -0,0 +1,31 @@ +

      \[ +1*2*3 multi-line math +\]

      + +

      \( 1*2*3 inline-math \)

      + +

      \[ 1*2*3 math with dollar \]

      + +

      \[ 1*2*3 \$ \\ \text{dollar with escapes} \]

      + +

      \( \\ \text{backslash with escapes} \$ 1*2*3 \)

      + +

      ( not really math )

      + +

      $$ also not math $$

      + +

      this$$ should not be$$ math

      + +

      nor $$ should $$this

      + +

      this \(*should* be\) math

      + +

      Something \{ like math but \} is not

      + +

      Also \(like math but \) is not

      + +

      \\( should not be math either \\)

      + +

      This is \( math, and the \\\( inner one \\\) should be \) preserved

      + +

      \[ did you <em> know </em> this is math? \]

      diff --git a/test/Tests/Math.text b/test/Tests/Math.text new file mode 100644 index 00000000..789c213a --- /dev/null +++ b/test/Tests/Math.text @@ -0,0 +1,31 @@ +\\[ +1*2*3 multi-line math +\\] + +\\( 1*2*3 inline-math \\) + +$$ 1*2*3 math with dollar $$ + +$$ 1*2*3 \$ \\ \text{dollar with escapes} $$ + +\\( \\ \text{backslash with escapes} \$ 1*2*3 \\) + +\( not *really* math \) + +\$$ also *not* math \$$ + +this$$ should *not* be$$ math + +nor $$ *should* $$this + +this $$*should* be$$ math + +Something \\{ like *math* but \\} is not + +Also \\\(like *math* but \\\) is not + +\\\\( should not be *math* either \\\\) + +This is \\( math, and the \\\( inner one \\\) should be \\) preserved + +$$ did you know this is math? $$ diff --git a/test/config.json b/test/config.json index cec160c6..bc6799cc 100644 --- a/test/config.json +++ b/test/config.json @@ -92,6 +92,11 @@ "input": "Tests/Escape character.text", "output": "Tests/Escape character.html", "skip": true + }, + { + "input": "Tests/Math.text", + "output": "Tests/Math.html", + "flags": ["--math"] } ] } diff --git a/test/runner.py b/test/runner.py index 5ebd78fe..fb64375e 100755 --- a/test/runner.py +++ b/test/runner.py @@ -2,18 +2,19 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function -import os -import sys -import copy +import difflib import json +import os import re +import sys import subprocess import unittest DLN = '======================================================================' SLN = '----------------------------------------------------------------------' TEST_ROOT = os.path.dirname(__file__) -HOEDOWN = [os.path.join(os.path.dirname(TEST_ROOT), 'hoedown')] +PROJECT_ROOT = os.path.dirname(TEST_ROOT) +HOEDOWN = [os.path.abspath(os.path.join(PROJECT_ROOT, 'hoedown'))] TIDY = ['tidy', '--show-body-only', '1', '--show-warnings', '0', '--quiet', '1'] CONFIG_PATH = os.path.join(TEST_ROOT, 'config.json') From 8c14212dd99f76608087a92d67bd9b93c67ac567 Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Tue, 9 Sep 2014 11:05:14 +0200 Subject: [PATCH 07/17] Use memcmp in hoedown_buffer_eq(...) --- src/buffer.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 6e96224b..8f9c17a4 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -121,11 +121,7 @@ int hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size) { if (buf->size != size) return 0; - - size_t i = 0; - while (i < size && buf->data[i] == data[i]) i++; - - return i == size; + return memcmp(buf->data, data, size) == 0; } int From 95ab7bb92fbe8230c96b3513a4714b61bb52bbb9 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 17:14:16 +0800 Subject: [PATCH 08/17] Enable escape character test --- test/config.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/config.json b/test/config.json index bc6799cc..63cb1d7f 100644 --- a/test/config.json +++ b/test/config.json @@ -90,8 +90,7 @@ }, { "input": "Tests/Escape character.text", - "output": "Tests/Escape character.html", - "skip": true + "output": "Tests/Escape character.html" }, { "input": "Tests/Math.text", From 6510aa4b76de4aa577d5cf394e8e629857052853 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 17:14:38 +0800 Subject: [PATCH 09/17] Use difflib to make error friendly --- test/runner.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/runner.py b/test/runner.py index fb64375e..6951d1d2 100755 --- a/test/runner.py +++ b/test/runner.py @@ -24,13 +24,9 @@ class TestFailed(AssertionError): def __init__(self, name, expected, got): super(TestFailed, self).__init__(self) - description_format = ( - '{name}\nExpected\n{sln}\n{expected}\n\n' - 'Got\n{sln}\n{got}\n\n' - ) - self.description = description_format.format( - dln=DLN, sln=SLN, name=name, - expected=expected.strip(), got=got.strip(), + diff = difflib.unified_diff(expected.splitlines(), got.splitlines(), 'Expected', 'Got') + self.description = '{name}\n{diff}'.format( + name=name, diff='\n'.join(diff), ) def __str__(self): @@ -48,14 +44,14 @@ def _test_func(test_case): TIDY, stdin=hoedown_proc.stdout, stdout=subprocess.PIPE, ) got_tidy_proc.wait() - got = got_tidy_proc.stdout.read() + got = got_tidy_proc.stdout.read().strip() expected_tidy_proc = subprocess.Popen( TIDY + [os.path.join(TEST_ROOT, test_case['output'])], stdout=subprocess.PIPE, ) expected_tidy_proc.wait() - expected = expected_tidy_proc.stdout.read() + expected = expected_tidy_proc.stdout.read().strip() try: assert expected == got From 9a2166db3cd1da2a2b2e6eb62539039dff12d399 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 17:16:08 +0800 Subject: [PATCH 10/17] Cleanup --- test/runner.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/runner.py b/test/runner.py index 6951d1d2..0d5f724a 100755 --- a/test/runner.py +++ b/test/runner.py @@ -6,7 +6,6 @@ import json import os import re -import sys import subprocess import unittest @@ -24,7 +23,10 @@ class TestFailed(AssertionError): def __init__(self, name, expected, got): super(TestFailed, self).__init__(self) - diff = difflib.unified_diff(expected.splitlines(), got.splitlines(), 'Expected', 'Got') + diff = difflib.unified_diff( + expected.splitlines(), got.splitlines(), + fromfile='Expected', tofile='Got', + ) self.description = '{name}\n{diff}'.format( name=name, diff='\n'.join(diff), ) From 855bc34742e710391588c95471014958f14c39d7 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 17:45:24 +0800 Subject: [PATCH 11/17] Make test script Python 3-compatible --- Makefile | 2 +- test/runner.py | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 66ead31c..56e15972 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ src/html_blocks.c: html_block_names.gperf # Testing test: hoedown - test/runner.py + python test/runner.py test-pl: hoedown perl test/MarkdownTest_1.0.3/MarkdownTest.pl \ diff --git a/test/runner.py b/test/runner.py index 0d5f724a..693a0eae 100755 --- a/test/runner.py +++ b/test/runner.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function +from __future__ import print_function import difflib import json import os @@ -20,6 +20,17 @@ SLUGIFY_PATTERN = re.compile(r'\W') +def with_metaclass(meta, *bases): + """Metaclass injection utility from six. + + See: https://pythonhosted.org/six/ + """ + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + class TestFailed(AssertionError): def __init__(self, name, expected, got): super(TestFailed, self).__init__(self) @@ -55,6 +66,11 @@ def _test_func(test_case): expected_tidy_proc.wait() expected = expected_tidy_proc.stdout.read().strip() + # Cleanup. + hoedown_proc.stdout.close() + got_tidy_proc.stdout.close() + expected_tidy_proc.stdout.close() + try: assert expected == got except AssertionError: @@ -65,7 +81,7 @@ def _make_test(test_case): return lambda self: _test_func(test_case) -class MarkdownTestCaseMeta(type): +class MarkdownTestsMeta(type): """Meta class for ``MarkdownTestCase`` to inject test cases on the fly. """ def __new__(meta, name, bases, attrs): @@ -85,8 +101,8 @@ def __new__(meta, name, bases, attrs): return type.__new__(meta, name, bases, attrs) -class MarkdownTestCase(unittest.TestCase): - __metaclass__ = MarkdownTestCaseMeta +class MarkdownTests(with_metaclass(MarkdownTestsMeta, unittest.TestCase)): + pass if __name__ == '__main__': From 9a0c20d1ad5773be370f1c3e4a2b84f8feb0b5fd Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 17:57:49 +0800 Subject: [PATCH 12/17] Add "fail" flag for expected failure Might be useful someday. --- test/runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/runner.py b/test/runner.py index 693a0eae..3c5e547e 100755 --- a/test/runner.py +++ b/test/runner.py @@ -97,6 +97,8 @@ def __new__(meta, name, bases, attrs): func.__doc__ = input_name if test.get('skip', False): func = unittest.skip(input_name)(func) + if test.get('fail', False): + func = unittest.expectsFailure(func) attrs[attr_name] = func return type.__new__(meta, name, bases, attrs) From 00a5b7abc25a3f88afb7f4f44c1328a119343270 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 9 Sep 2014 17:59:15 +0800 Subject: [PATCH 13/17] Cleanup --- test/runner.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/runner.py b/test/runner.py index 3c5e547e..4102fad4 100755 --- a/test/runner.py +++ b/test/runner.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from __future__ import print_function import difflib import json import os @@ -9,8 +8,6 @@ import subprocess import unittest -DLN = '======================================================================' -SLN = '----------------------------------------------------------------------' TEST_ROOT = os.path.dirname(__file__) PROJECT_ROOT = os.path.dirname(TEST_ROOT) HOEDOWN = [os.path.abspath(os.path.join(PROJECT_ROOT, 'hoedown'))] From d0759dd2081d69dee4d82602fb3690c8115aa1b5 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 14 Sep 2014 00:21:08 +0200 Subject: [PATCH 14/17] Include strings.h to silence warnings for strncasecmp --- src/autolink.c | 4 +++- src/document.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/autolink.c b/src/autolink.c index 5d18fb53..7a99d50f 100644 --- a/src/autolink.c +++ b/src/autolink.c @@ -5,7 +5,9 @@ #include #include -#ifdef _MSC_VER +#ifndef _MSC_VER +#include +#else #define strncasecmp _strnicmp #endif diff --git a/src/document.c b/src/document.c index a8562057..e32a13c2 100644 --- a/src/document.c +++ b/src/document.c @@ -7,7 +7,9 @@ #include "stack.h" -#ifdef _MSC_VER +#ifndef _MSC_VER +#include +#else #define strncasecmp _strnicmp #endif From 521517291413e528c283ee92f8738f84078ea5ae Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Sun, 14 Sep 2014 19:00:10 +0200 Subject: [PATCH 15/17] Don't require spacing around math spans (fix #120) --- src/document.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/document.c b/src/document.c index e32a13c2..7d8eedaf 100644 --- a/src/document.c +++ b/src/document.c @@ -734,13 +734,9 @@ parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs /* prepare buffers */ hoedown_buffer text = { data + delimsz, i - delimsz, 0, 0, NULL, NULL, NULL }; - /* enforce spacing around the span */ - i += delimsz; - if (offset && !_isspace(data[-1])) return 0; - if (i < size && !_isspace(data[i])) return 0; - /* if this is a $$ and MATH_EXPLICIT is not active, * guess wether displaymode should be enabled from the context */ + i += delimsz; if (delimsz == 2 && !(doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT)) displaymode = is_empty_all(data - offset, offset) && is_empty_all(data + i, size - i); From 5c6ef747397e2b7c56fd758323ad153501414b11 Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Sun, 14 Sep 2014 19:16:41 +0200 Subject: [PATCH 16/17] Modify tests accordingly --- test/Tests/Math.html | 8 ++++---- test/Tests/Math.text | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/Tests/Math.html b/test/Tests/Math.html index 5e2fd3eb..72df249b 100644 --- a/test/Tests/Math.html +++ b/test/Tests/Math.html @@ -14,17 +14,17 @@

      $$ also not math $$

      -

      this$$ should not be$$ math

      +

      this \(*should* be\) math

      -

      nor $$ should $$this

      +

      this\( *should* also be\) math

      -

      this \(*should* be\) math

      +

      and \(this *should* \)too

      Something \{ like math but \} is not

      Also \(like math but \) is not

      -

      \\( should not be math either \\)

      +

      \\( should be *math* as well \\\)

      This is \( math, and the \\\( inner one \\\) should be \) preserved

      diff --git a/test/Tests/Math.text b/test/Tests/Math.text index 789c213a..dbca4016 100644 --- a/test/Tests/Math.text +++ b/test/Tests/Math.text @@ -14,17 +14,17 @@ $$ 1*2*3 \$ \\ \text{dollar with escapes} $$ \$$ also *not* math \$$ -this$$ should *not* be$$ math +this $$*should* be$$ math -nor $$ *should* $$this +this$$ *should* also be$$ math -this $$*should* be$$ math +and $$this *should* $$too Something \\{ like *math* but \\} is not Also \\\(like *math* but \\\) is not -\\\\( should not be *math* either \\\\) +\\\\( should be *math* as well \\\\) This is \\( math, and the \\\( inner one \\\) should be \\) preserved From 108ee1a463b12ea8d8dedf7e4447161bff52755a Mon Sep 17 00:00:00 2001 From: Xavier Mendez Date: Fri, 19 Sep 2014 17:45:32 +0200 Subject: [PATCH 17/17] Remove HTML_SAFELINK and EXT_LAX_SPACING --- bin/hoedown.c | 2 -- src/document.c | 31 ------------------------------- src/document.h | 2 -- src/html.c | 8 -------- src/html.h | 5 ++--- 5 files changed, 2 insertions(+), 46 deletions(-) diff --git a/bin/hoedown.c b/bin/hoedown.c index 9ef22dbe..eb3ea5d3 100644 --- a/bin/hoedown.c +++ b/bin/hoedown.c @@ -66,7 +66,6 @@ static struct extension_info extensions_info[] = { {HOEDOWN_EXT_SUPERSCRIPT, "superscript", "Parse super^script."}, {HOEDOWN_EXT_MATH, "math", "Parse TeX $$math$$ syntax, Kramdown style."}, - {HOEDOWN_EXT_LAX_SPACING, "lax-spacing", "Don't require a blank line between some blocks."}, {HOEDOWN_EXT_NO_INTRA_EMPHASIS, "disable-intra-emphasis", "Disable emphasis_between_words."}, {HOEDOWN_EXT_SPACE_HEADERS, "space-headers", "Require a space after '#' in headers."}, {HOEDOWN_EXT_MATH_EXPLICIT, "math-explicit", "Instead of guessing by context, parse $inline math$ and $$always block math$$ (requires --math)."}, @@ -77,7 +76,6 @@ static struct extension_info extensions_info[] = { static struct html_flag_info html_flags_info[] = { {HOEDOWN_HTML_SKIP_HTML, "skip-html", "Strip all HTML tags."}, {HOEDOWN_HTML_ESCAPE, "escape", "Escape all HTML."}, - {HOEDOWN_HTML_SAFELINK, "safelink", "Only allow links to safe protocols."}, {HOEDOWN_HTML_HARD_WRAP, "hard-wrap", "Render each linebreak as
      ."}, {HOEDOWN_HTML_USE_XHTML, "xhtml", "Render XHTML."}, }; diff --git a/src/document.c b/src/document.c index 7d8eedaf..ddee0e18 100644 --- a/src/document.c +++ b/src/document.c @@ -1638,37 +1638,6 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t break; } - /* - * Early termination of a paragraph with the same logic - * as Markdown 1.0.0. If this logic is applied, the - * Markdown 1.0.3 test suite won't pass cleanly - * - * :: If the first character in a new line is not a letter, - * let's check to see if there's some kind of block starting - * here - */ - if ((doc->ext_flags & HOEDOWN_EXT_LAX_SPACING) && !isalnum(data[i])) { - if (prefix_oli(data + i, size - i) || - prefix_uli(data + i, size - i)) { - end = i; - break; - } - - /* see if an html block starts here */ - if (data[i] == '<' && doc->md.blockhtml && - parse_htmlblock(ob, doc, data + i, size - i, 0)) { - end = i; - break; - } - - /* see if a code fence starts here */ - if ((doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) != 0 && - is_codefence(data + i, size - i, NULL, NULL)) { - end = i; - break; - } - } - i = end; } diff --git a/src/document.h b/src/document.h index e586ef2e..19013352 100644 --- a/src/document.h +++ b/src/document.h @@ -31,7 +31,6 @@ typedef enum hoedown_extensions { HOEDOWN_EXT_MATH = (1 << 9), /* other flags */ - HOEDOWN_EXT_LAX_SPACING = (1 << 10), HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11), HOEDOWN_EXT_SPACE_HEADERS = (1 << 12), HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13), @@ -55,7 +54,6 @@ typedef enum hoedown_extensions { HOEDOWN_EXT_MATH ) #define HOEDOWN_EXT_FLAGS (\ - HOEDOWN_EXT_LAX_SPACING |\ HOEDOWN_EXT_NO_INTRA_EMPHASIS |\ HOEDOWN_EXT_SPACE_HEADERS |\ HOEDOWN_EXT_MATH_EXPLICIT ) diff --git a/src/html.c b/src/html.c index 231b8b7f..81ac1f1b 100644 --- a/src/html.c +++ b/src/html.c @@ -63,11 +63,6 @@ rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_t if (!link || !link->size) return 0; - if ((state->flags & HOEDOWN_HTML_SAFELINK) != 0 && - !hoedown_autolink_is_safe(link->data, link->size) && - type != HOEDOWN_AUTOLINK_EMAIL) - return 0; - HOEDOWN_BUFPUTSL(ob, "flags & HOEDOWN_HTML_SAFELINK) != 0 && !hoedown_autolink_is_safe(link->data, link->size)) - return 0; - HOEDOWN_BUFPUTSL(ob, "size) diff --git a/src/html.h b/src/html.h index 8e321d82..449dcada 100644 --- a/src/html.h +++ b/src/html.h @@ -18,9 +18,8 @@ extern "C" { typedef enum hoedown_html_flags { HOEDOWN_HTML_SKIP_HTML = (1 << 0), HOEDOWN_HTML_ESCAPE = (1 << 1), - HOEDOWN_HTML_SAFELINK = (1 << 2), - HOEDOWN_HTML_HARD_WRAP = (1 << 3), - HOEDOWN_HTML_USE_XHTML = (1 << 4) + HOEDOWN_HTML_HARD_WRAP = (1 << 2), + HOEDOWN_HTML_USE_XHTML = (1 << 3) } hoedown_html_flags; typedef enum hoedown_html_tag {