Import improvements from Lanli (and more things)

This commit is contained in:
Xavier Mendez 2014-09-02 19:21:58 +02:00
parent c6238419ff
commit a6b90a7cf7
16 changed files with 457 additions and 399 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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 (size_t i = 0; i < valid_uris_count; ++i) {
size_t len = valid_uris_size[i];
for (i = 0; i < valid_uris_count; ++i) {
size_t len = strlen(valid_uris[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;
}

View file

@ -9,24 +9,35 @@
extern "C" {
#endif
enum {
/*************
* CONSTANTS *
*************/
typedef enum hoedown_autolink_flags {
HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0)
};
} hoedown_autolink_flags;
int
hoedown_autolink_is_safe(const uint8_t *link, size_t link_len);
size_t
hoedown_autolink__www(size_t *rewind_p, hoedown_buffer *link,
uint8_t *data, size_t offset, size_t size, unsigned int flags);
/*************
* FUNCTIONS *
*************/
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_is_safe: verify that a URL has a safe protocol */
int hoedown_autolink_is_safe(const uint8_t *data, size_t size);
/* 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);
/* 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);
/* 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
}

View file

@ -5,7 +5,6 @@
#include <string.h>
#include <assert.h>
/* 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);

View file

@ -3,9 +3,11 @@
#ifndef HOEDOWN_BUFFER_H
#define HOEDOWN_BUFFER_H
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#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

View file

@ -1,5 +1,3 @@
/* document.c - generic markdown parser */
#include "document.h"
#include <assert.h>
@ -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);
}

View file

@ -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) /* <li> 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));
extern void
hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size);
/* 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_inline(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);
/* 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
}

View file

@ -4,6 +4,11 @@
#include <stdio.h>
#include <string.h>
#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, "&amp;");
break;
@ -91,7 +94,7 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size)
case '\'':
HOEDOWN_BUFPUTSL(ob, "&#x27;");
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, 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;
size_t i = 0, mark;
while (i < size) {
org = i;
while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
i++;
while (1) {
mark = i;
while (i < size && HTML_ESCAPE_TABLE[data[i]] == 0) i++;
if (i > org) {
if (org == 0) {
if (i >= size) {
hoedown_buffer_put(ob, src, size);
return;
}
}
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++;

View file

@ -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
}

View file

@ -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 ? "<ol>\n" : "<ul>\n", 5);
hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "<ol>\n" : "<ul>\n"), 5);
if (text) hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, flags & HOEDOWN_LIST_ORDERED ? "</ol>\n" : "</ul>\n", 6);
hoedown_buffer_put(ob, (uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "</ol>\n" : "</ul>\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, "<th");
@ -489,10 +489,10 @@ rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
HOEDOWN_BUFPUTSL(ob, "<div class=\"footnotes\">\n");
hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
HOEDOWN_BUFPUTSL(ob, "<ol>\n");
if (text)
hoedown_buffer_put(ob, text->data, text->size);
HOEDOWN_BUFPUTSL(ob, "\n</ol>\n</div>\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<li id=\"fn%d\">\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;
}

View file

@ -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 <stdlib.h>
#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 *
*************/
extern hoedown_renderer *
hoedown_html_toc_renderer_new(int nesting_level);
/* 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);
extern void
hoedown_html_renderer_free(hoedown_renderer *renderer);
/* 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));
/* 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));
/* 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
}

View file

@ -1,25 +1,29 @@
#include "stack.h"
#include <string.h>
#include "buffer.h"
int
hoedown_stack_new(hoedown_stack *st, size_t initial_size)
#include <stdlib.h>
#include <string.h>
#include <assert.h>
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;
assert(st);
if (st->asize >= new_size)
return 0;
if (st->asize >= neosz)
return;
new_st = realloc(st->item, new_size * sizeof(void *));
if (new_st == NULL)
return -1;
st->item = hoedown_realloc(st->item, neosz * sizeof(void *));
memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *));
st->asize = neosz;
memset(new_st + st->asize, 0x0,
(new_size - st->asize) * sizeof(void *));
st->item = new_st;
st->asize = new_size;
if (st->size > new_size)
st->size = new_size;
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;

View file

@ -3,26 +3,47 @@
#ifndef HOEDOWN_STACK_H
#define HOEDOWN_STACK_H
#include <stdlib.h>
#include <stddef.h>
#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
}

View file

@ -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
}