Import improvements from Lanli (and more things)
This commit is contained in:
parent
c6238419ff
commit
a6b90a7cf7
16 changed files with 457 additions and 399 deletions
2
Makefile
2
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)
|
ifneq ($(OS),Windows_NT)
|
||||||
CFLAGS += -fPIC
|
CFLAGS += -fPIC
|
||||||
|
|
|
@ -399,20 +399,13 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* reading everything */
|
/* reading everything */
|
||||||
ib = hoedown_buffer_new(iunit);
|
ib = hoedown_buffer_new(iunit);
|
||||||
if (!ib) {
|
|
||||||
fprintf(stderr, "Couldn't allocate input buffer.\n");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!feof(in)) {
|
while (!feof(in)) {
|
||||||
if (ferror(in)) {
|
if (ferror(in)) {
|
||||||
fprintf(stderr, "I/O errors found while reading input.\n");
|
fprintf(stderr, "I/O errors found while reading input.\n");
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
if (hoedown_buffer_grow(ib, ib->size + iunit) != HOEDOWN_BUF_OK) {
|
hoedown_buffer_grow(ib, ib->size + iunit);
|
||||||
fprintf(stderr, "Couldn't grow input buffer.\n");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
ib->size += fread(ib->data + ib->size, 1, iunit, in);
|
ib->size += fread(ib->data + ib->size, 1, iunit, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,8 +414,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
|
|
||||||
/* creating the renderer */
|
/* creating the renderer */
|
||||||
hoedown_renderer *renderer;
|
hoedown_renderer *renderer = NULL;
|
||||||
void (*renderer_free)(hoedown_renderer*);
|
void (*renderer_free)(hoedown_renderer*) = NULL;
|
||||||
|
|
||||||
switch (renderer_type) {
|
switch (renderer_type) {
|
||||||
case RENDERER_HTML:
|
case RENDERER_HTML:
|
||||||
|
@ -437,29 +430,12 @@ main(int argc, char **argv)
|
||||||
renderer = null_renderer_new();
|
renderer = null_renderer_new();
|
||||||
renderer_free = null_renderer_free;
|
renderer_free = null_renderer_free;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
renderer = NULL;
|
|
||||||
renderer_free = NULL;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!renderer) {
|
|
||||||
fprintf(stderr, "Couldn't allocate renderer.\n");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* performing markdown rendering */
|
/* performing markdown rendering */
|
||||||
ob = hoedown_buffer_new(ounit);
|
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);
|
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);
|
//clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
hoedown_document_render(document, ob, ib->data, ib->size);
|
hoedown_document_render(document, ob, ib->data, ib->size);
|
||||||
|
|
|
@ -183,20 +183,13 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* reading everything */
|
/* reading everything */
|
||||||
ib = hoedown_buffer_new(iunit);
|
ib = hoedown_buffer_new(iunit);
|
||||||
if (!ib) {
|
|
||||||
fprintf(stderr, "Couldn't allocate input buffer.\n");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!feof(in)) {
|
while (!feof(in)) {
|
||||||
if (ferror(in)) {
|
if (ferror(in)) {
|
||||||
fprintf(stderr, "I/O errors found while reading input.\n");
|
fprintf(stderr, "I/O errors found while reading input.\n");
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
if (hoedown_buffer_grow(ib, ib->size + iunit) != HOEDOWN_BUF_OK) {
|
hoedown_buffer_grow(ib, ib->size + iunit);
|
||||||
fprintf(stderr, "Couldn't grow input buffer.\n");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
ib->size += fread(ib->data + ib->size, 1, iunit, in);
|
ib->size += fread(ib->data + ib->size, 1, iunit, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,10 +199,6 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* performing SmartyPants processing */
|
/* performing SmartyPants processing */
|
||||||
ob = hoedown_buffer_new(ounit);
|
ob = hoedown_buffer_new(ounit);
|
||||||
if (!ob) {
|
|
||||||
fprintf(stderr, "Couldn't allocate output buffer.\n");
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
//clock_gettime(CLOCK_MONOTONIC, &start);
|
//clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
hoedown_html_smartypants(ob, ib->data, ib->size);
|
hoedown_html_smartypants(ob, ib->data, ib->size);
|
||||||
|
|
|
@ -10,21 +10,20 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
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 size_t valid_uris_count = 6;
|
||||||
static const char *valid_uris[] = {
|
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) {
|
if (size > len &&
|
||||||
size_t len = strlen(valid_uris[i]);
|
strncasecmp((char *)data, valid_uris[i], len) == 0 &&
|
||||||
|
isalnum(data[len]))
|
||||||
if (link_len > len &&
|
|
||||||
strncasecmp((char *)link, valid_uris[i], len) == 0 &&
|
|
||||||
isalnum(link[len]))
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,24 +9,35 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
|
||||||
|
/*************
|
||||||
|
* CONSTANTS *
|
||||||
|
*************/
|
||||||
|
|
||||||
|
typedef enum hoedown_autolink_flags {
|
||||||
HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0)
|
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,
|
* FUNCTIONS *
|
||||||
uint8_t *data, size_t offset, size_t size, unsigned int flags);
|
*************/
|
||||||
|
|
||||||
size_t
|
/* hoedown_autolink_is_safe: verify that a URL has a safe protocol */
|
||||||
hoedown_autolink__email(size_t *rewind_p, hoedown_buffer *link,
|
int hoedown_autolink_is_safe(const uint8_t *data, size_t size);
|
||||||
uint8_t *data, size_t offset, size_t size, unsigned int flags);
|
|
||||||
|
/* 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
117
src/buffer.c
117
src/buffer.c
|
@ -5,7 +5,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
/* hoedown_buffer_init: initialize a buffer with custom allocators */
|
|
||||||
void
|
void
|
||||||
hoedown_buffer_init(
|
hoedown_buffer_init(
|
||||||
hoedown_buffer *buf,
|
hoedown_buffer *buf,
|
||||||
|
@ -14,8 +13,7 @@ hoedown_buffer_init(
|
||||||
hoedown_free_callback data_free,
|
hoedown_free_callback data_free,
|
||||||
hoedown_free_callback buffer_free)
|
hoedown_free_callback buffer_free)
|
||||||
{
|
{
|
||||||
if (!buf)
|
assert(buf);
|
||||||
return;
|
|
||||||
|
|
||||||
buf->data = NULL;
|
buf->data = NULL;
|
||||||
buf->size = buf->asize = 0;
|
buf->size = buf->asize = 0;
|
||||||
|
@ -25,21 +23,18 @@ hoedown_buffer_init(
|
||||||
buf->buffer_free = buffer_free;
|
buf->buffer_free = buffer_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_new: allocation of a new buffer */
|
|
||||||
hoedown_buffer *
|
hoedown_buffer *
|
||||||
hoedown_buffer_new(size_t unit)
|
hoedown_buffer_new(size_t unit)
|
||||||
{
|
{
|
||||||
hoedown_buffer *ret = malloc(sizeof (hoedown_buffer));
|
hoedown_buffer *ret = hoedown_malloc(sizeof (hoedown_buffer));
|
||||||
hoedown_buffer_init(ret, unit, realloc, free, free);
|
hoedown_buffer_init(ret, unit, hoedown_realloc, free, free);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_free: decrease the reference count and free the buffer if needed */
|
|
||||||
void
|
void
|
||||||
hoedown_buffer_free(hoedown_buffer *buf)
|
hoedown_buffer_free(hoedown_buffer *buf)
|
||||||
{
|
{
|
||||||
if (!buf)
|
if (!buf) return;
|
||||||
return;
|
|
||||||
|
|
||||||
buf->data_free(buf->data);
|
buf->data_free(buf->data);
|
||||||
|
|
||||||
|
@ -47,84 +42,104 @@ hoedown_buffer_free(hoedown_buffer *buf)
|
||||||
buf->buffer_free(buf);
|
buf->buffer_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_reset: frees internal data of the buffer */
|
|
||||||
void
|
void
|
||||||
hoedown_buffer_reset(hoedown_buffer *buf)
|
hoedown_buffer_reset(hoedown_buffer *buf)
|
||||||
{
|
{
|
||||||
if (!buf)
|
assert(buf && buf->unit);
|
||||||
return;
|
|
||||||
|
|
||||||
buf->data_free(buf->data);
|
buf->data_free(buf->data);
|
||||||
buf->data = NULL;
|
buf->data = NULL;
|
||||||
buf->size = buf->asize = 0;
|
buf->size = buf->asize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_grow: increasing the allocated size to the given value */
|
void
|
||||||
int
|
|
||||||
hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz)
|
hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz)
|
||||||
{
|
{
|
||||||
size_t neoasz;
|
size_t neoasz;
|
||||||
void *neodata;
|
|
||||||
|
|
||||||
assert(buf && buf->unit);
|
assert(buf && buf->unit);
|
||||||
|
|
||||||
if (buf->asize >= neosz)
|
if (buf->asize >= neosz)
|
||||||
return HOEDOWN_BUF_OK;
|
return;
|
||||||
|
|
||||||
neoasz = buf->asize + buf->unit;
|
neoasz = buf->asize + buf->unit;
|
||||||
while (neoasz < neosz)
|
while (neoasz < neosz)
|
||||||
neoasz += buf->unit;
|
neoasz += buf->unit;
|
||||||
|
|
||||||
neodata = buf->data_realloc(buf->data, neoasz);
|
buf->data = buf->data_realloc(buf->data, neoasz);
|
||||||
if (!neodata)
|
|
||||||
return HOEDOWN_BUF_ENOMEM;
|
|
||||||
|
|
||||||
buf->data = neodata;
|
|
||||||
buf->asize = neoasz;
|
buf->asize = neoasz;
|
||||||
return HOEDOWN_BUF_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_put: appends raw data to a buffer */
|
|
||||||
void
|
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);
|
assert(buf && buf->unit);
|
||||||
|
|
||||||
if (buf->size + len > buf->asize && hoedown_buffer_grow(buf, buf->size + len) < 0)
|
if (buf->size + size > buf->asize)
|
||||||
return;
|
hoedown_buffer_grow(buf, buf->size + size);
|
||||||
|
|
||||||
memcpy(buf->data + buf->size, data, len);
|
memcpy(buf->data + buf->size, data, size);
|
||||||
buf->size += len;
|
buf->size += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_puts: appends a NUL-terminated string to a buffer */
|
|
||||||
void
|
void
|
||||||
hoedown_buffer_puts(hoedown_buffer *buf, const char *str)
|
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
|
void
|
||||||
hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c)
|
hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c)
|
||||||
{
|
{
|
||||||
assert(buf && buf->unit);
|
assert(buf && buf->unit);
|
||||||
|
|
||||||
if (buf->size + 1 > buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0)
|
if (buf->size >= buf->asize)
|
||||||
return;
|
hoedown_buffer_grow(buf, buf->size + 1);
|
||||||
|
|
||||||
buf->data[buf->size] = c;
|
buf->data[buf->size] = c;
|
||||||
buf->size += 1;
|
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
|
int
|
||||||
hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix)
|
hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
assert(buf && buf->unit);
|
assert(buf && buf->unit);
|
||||||
|
|
||||||
for (i = 0; i < buf->size; ++i) {
|
for (size_t i = 0; i < buf->size; ++i) {
|
||||||
if (prefix[i] == 0)
|
if (prefix[i] == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -135,22 +150,20 @@ hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_slurp: removes a given number of bytes from the head of the array */
|
|
||||||
void
|
void
|
||||||
hoedown_buffer_slurp(hoedown_buffer *buf, size_t len)
|
hoedown_buffer_slurp(hoedown_buffer *buf, size_t size)
|
||||||
{
|
{
|
||||||
assert(buf && buf->unit);
|
assert(buf && buf->unit);
|
||||||
|
|
||||||
if (len >= buf->size) {
|
if (size >= buf->size) {
|
||||||
buf->size = 0;
|
buf->size = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->size -= len;
|
buf->size -= size;
|
||||||
memmove(buf->data, buf->data + len, buf->size);
|
memmove(buf->data, buf->data + size, buf->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_cstr: NULL-termination of the string array */
|
|
||||||
const char *
|
const char *
|
||||||
hoedown_buffer_cstr(hoedown_buffer *buf)
|
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)
|
if (buf->size < buf->asize && buf->data[buf->size] == 0)
|
||||||
return (char *)buf->data;
|
return (char *)buf->data;
|
||||||
|
|
||||||
if (buf->size + 1 <= buf->asize || hoedown_buffer_grow(buf, buf->size + 1) == 0) {
|
hoedown_buffer_grow(buf, buf->size + 1);
|
||||||
buf->data[buf->size] = 0;
|
buf->data[buf->size] = 0;
|
||||||
return (char *)buf->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return (char *)buf->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hoedown_buffer_printf: formatted printing to a buffer */
|
|
||||||
void
|
void
|
||||||
hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...)
|
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);
|
assert(buf && buf->unit);
|
||||||
|
|
||||||
if (buf->size >= buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0)
|
if (buf->size >= buf->asize)
|
||||||
return;
|
hoedown_buffer_grow(buf, buf->size + 1);
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
||||||
va_end(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 ((size_t)n >= buf->asize - buf->size) {
|
||||||
if (hoedown_buffer_grow(buf, buf->size + n + 1) < 0)
|
hoedown_buffer_grow(buf, buf->size + n + 1);
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
||||||
|
|
88
src/buffer.h
88
src/buffer.h
|
@ -3,9 +3,11 @@
|
||||||
#ifndef HOEDOWN_BUFFER_H
|
#ifndef HOEDOWN_BUFFER_H
|
||||||
#define HOEDOWN_BUFFER_H
|
#define HOEDOWN_BUFFER_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -16,15 +18,14 @@ extern "C" {
|
||||||
#define inline __inline
|
#define inline __inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
HOEDOWN_BUF_OK = 0,
|
/*********
|
||||||
HOEDOWN_BUF_ENOMEM = -1
|
* TYPES *
|
||||||
} hoedown_buferror_t;
|
*********/
|
||||||
|
|
||||||
typedef void *(*hoedown_realloc_callback)(void *, size_t);
|
typedef void *(*hoedown_realloc_callback)(void *, size_t);
|
||||||
typedef void (*hoedown_free_callback)(void *);
|
typedef void (*hoedown_free_callback)(void *);
|
||||||
|
|
||||||
/* hoedown_buffer: character array buffer */
|
|
||||||
struct hoedown_buffer {
|
struct hoedown_buffer {
|
||||||
uint8_t *data; /* actual character data */
|
uint8_t *data; /* actual character data */
|
||||||
size_t size; /* size of the string */
|
size_t size; /* size of the string */
|
||||||
|
@ -35,12 +36,29 @@ struct hoedown_buffer {
|
||||||
hoedown_free_callback data_free;
|
hoedown_free_callback data_free;
|
||||||
hoedown_free_callback buffer_free;
|
hoedown_free_callback buffer_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct hoedown_buffer hoedown_buffer;
|
typedef struct hoedown_buffer hoedown_buffer;
|
||||||
|
|
||||||
/* HOEDOWN_BUFPUTSL: optimized hoedown_buffer_puts of a string literal */
|
/* malloc / realloc / calloc wrappers */
|
||||||
#define HOEDOWN_BUFPUTSL(output, literal) \
|
#define HOEDOWN_ALLOC_WRAPPER(sig, call) \
|
||||||
hoedown_buffer_put(output, literal, sizeof(literal) - 1)
|
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 */
|
/* hoedown_buffer_init: initialize a buffer with custom allocators */
|
||||||
void hoedown_buffer_init(
|
void hoedown_buffer_init(
|
||||||
|
@ -51,32 +69,41 @@ void hoedown_buffer_init(
|
||||||
hoedown_free_callback buffer_free
|
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 *hoedown_buffer_new(size_t unit) __attribute__ ((malloc));
|
||||||
|
|
||||||
/* hoedown_buffer_free: decrease the reference count and free the buffer if needed */
|
/* hoedown_buffer_reset: free internal data of the buffer */
|
||||||
void hoedown_buffer_free(hoedown_buffer *buf);
|
|
||||||
|
|
||||||
/* hoedown_buffer_reset: frees internal data of the buffer */
|
|
||||||
void hoedown_buffer_reset(hoedown_buffer *buf);
|
void hoedown_buffer_reset(hoedown_buffer *buf);
|
||||||
|
|
||||||
/* hoedown_buffer_grow: increasing the allocated size to the given value */
|
/* hoedown_buffer_grow: increase the allocated size to the given value */
|
||||||
int hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz);
|
void hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz);
|
||||||
|
|
||||||
/* hoedown_buffer_put: appends raw data to a buffer */
|
/* hoedown_buffer_put: append raw data to a buffer */
|
||||||
void hoedown_buffer_put(hoedown_buffer *buf, const void *data, size_t len);
|
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);
|
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);
|
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 */
|
/* hoedown_buffer_prefix: compare the beginning of a buffer with a string */
|
||||||
int hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix);
|
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 */
|
/* hoedown_buffer_slurp: remove a given number of bytes from the head of the buffer */
|
||||||
void hoedown_buffer_slurp(hoedown_buffer *buf, size_t len);
|
void hoedown_buffer_slurp(hoedown_buffer *buf, size_t size);
|
||||||
|
|
||||||
/* hoedown_buffer_cstr: NUL-termination of the string array (making a C-string) */
|
/* hoedown_buffer_cstr: NUL-termination of the string array (making a C-string) */
|
||||||
const char *hoedown_buffer_cstr(hoedown_buffer *buf);
|
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 */
|
/* hoedown_buffer_printf: formatted printing to a buffer */
|
||||||
void hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
101
src/document.c
101
src/document.c
|
@ -1,5 +1,3 @@
|
||||||
/* document.c - generic markdown parser */
|
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -120,7 +118,7 @@ struct hoedown_document {
|
||||||
struct footnote_list footnotes_used;
|
struct footnote_list footnotes_used;
|
||||||
uint8_t active_char[256];
|
uint8_t active_char[256];
|
||||||
hoedown_stack work_bufs[2];
|
hoedown_stack work_bufs[2];
|
||||||
unsigned int ext_flags;
|
hoedown_extensions ext_flags;
|
||||||
size_t max_nesting;
|
size_t max_nesting;
|
||||||
int in_link_body;
|
int in_link_body;
|
||||||
};
|
};
|
||||||
|
@ -191,10 +189,7 @@ add_link_ref(
|
||||||
struct link_ref **references,
|
struct link_ref **references,
|
||||||
const uint8_t *name, size_t name_size)
|
const uint8_t *name, size_t name_size)
|
||||||
{
|
{
|
||||||
struct link_ref *ref = calloc(1, sizeof(struct link_ref));
|
struct link_ref *ref = hoedown_calloc(1, sizeof(struct link_ref));
|
||||||
|
|
||||||
if (!ref)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ref->id = hash_link_ref(name, name_size);
|
ref->id = hash_link_ref(name, name_size);
|
||||||
ref->next = references[ref->id % REF_TABLE_SIZE];
|
ref->next = references[ref->id % REF_TABLE_SIZE];
|
||||||
|
@ -243,9 +238,7 @@ free_link_refs(struct link_ref **references)
|
||||||
static struct footnote_ref *
|
static struct footnote_ref *
|
||||||
create_footnote_ref(struct footnote_list *list, const uint8_t *name, size_t name_size)
|
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));
|
struct footnote_ref *ref = hoedown_calloc(1, sizeof(struct footnote_ref));
|
||||||
if (!ref)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ref->id = hash_link_ref(name, name_size);
|
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
|
static int
|
||||||
add_footnote_ref(struct footnote_list *list, struct footnote_ref *ref)
|
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)
|
if (!item)
|
||||||
return 0;
|
return 0;
|
||||||
item->ref = ref;
|
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 */
|
/* tag_length • returns the length of the given tag, or 0 is it's not valid */
|
||||||
static size_t
|
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;
|
size_t i, j;
|
||||||
|
|
||||||
|
@ -453,8 +446,8 @@ static void
|
||||||
parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
|
parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
|
||||||
{
|
{
|
||||||
size_t i = 0, end = 0;
|
size_t i = 0, end = 0;
|
||||||
uint8_t action = 0;
|
|
||||||
hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
|
hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
|
||||||
|
uint8_t *active_char = doc->active_char;
|
||||||
|
|
||||||
if (doc->work_bufs[BUFFER_SPAN].size +
|
if (doc->work_bufs[BUFFER_SPAN].size +
|
||||||
doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
|
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) {
|
while (i < size) {
|
||||||
/* copying inactive chars into the output */
|
/* 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++;
|
end++;
|
||||||
}
|
|
||||||
|
|
||||||
if (doc->md.normal_text) {
|
if (doc->md.normal_text) {
|
||||||
work.data = data + i;
|
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;
|
if (end >= size) break;
|
||||||
i = end;
|
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 */
|
if (!end) /* no action from the callback */
|
||||||
end = i + 1;
|
end = i + 1;
|
||||||
else {
|
else {
|
||||||
|
@ -907,7 +899,7 @@ char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off
|
||||||
static size_t
|
static size_t
|
||||||
char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
|
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);
|
size_t end = tag_length(data, size, &altype);
|
||||||
hoedown_buffer work = { data, end, 0, 0, NULL, NULL, NULL };
|
hoedown_buffer work = { data, end, 0, 0, NULL, NULL, NULL };
|
||||||
int ret = 0;
|
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 */
|
/* parse_listitem • parsing of a single list item */
|
||||||
/* assuming initial prefix is already removed */
|
/* assuming initial prefix is already removed */
|
||||||
static size_t
|
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;
|
hoedown_buffer *work = 0, *inter = 0;
|
||||||
size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
|
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 */
|
/* parse_list • parsing ordered or unordered list block */
|
||||||
static size_t
|
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;
|
hoedown_buffer *work = 0;
|
||||||
size_t i = 0, j;
|
size_t i = 0, j;
|
||||||
|
@ -2044,7 +2036,7 @@ htmlblock_find_end_strict(
|
||||||
while (i < size && data[i] != '\n') i++;
|
while (i < size && data[i] != '\n') i++;
|
||||||
if (i < size) i++;
|
if (i < size) i++;
|
||||||
if (i == mark) return 0;
|
if (i == mark) return 0;
|
||||||
|
|
||||||
if (data[mark] == ' ' && mark > 0) continue;
|
if (data[mark] == ' ' && mark > 0) continue;
|
||||||
mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark);
|
mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark);
|
||||||
if (mark == i && (is_empty(data + i, size - i) || i >= size)) break;
|
if (mark == i && (is_empty(data + i, size - i) || i >= size)) break;
|
||||||
|
@ -2144,8 +2136,8 @@ parse_table_row(
|
||||||
uint8_t *data,
|
uint8_t *data,
|
||||||
size_t size,
|
size_t size,
|
||||||
size_t columns,
|
size_t columns,
|
||||||
int *col_data,
|
hoedown_tableflags *col_data,
|
||||||
int header_flag)
|
hoedown_tableflags header_flag)
|
||||||
{
|
{
|
||||||
size_t i = 0, col;
|
size_t i = 0, col;
|
||||||
hoedown_buffer *row_work = 0;
|
hoedown_buffer *row_work = 0;
|
||||||
|
@ -2201,7 +2193,7 @@ parse_table_header(
|
||||||
uint8_t *data,
|
uint8_t *data,
|
||||||
size_t size,
|
size_t size,
|
||||||
size_t *columns,
|
size_t *columns,
|
||||||
int **column_data)
|
hoedown_tableflags **column_data)
|
||||||
{
|
{
|
||||||
int pipes;
|
int pipes;
|
||||||
size_t i = 0, col, header_end, under_end;
|
size_t i = 0, col, header_end, under_end;
|
||||||
|
@ -2229,7 +2221,7 @@ parse_table_header(
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*columns = pipes + 1;
|
*columns = pipes + 1;
|
||||||
*column_data = calloc(*columns, sizeof(int));
|
*column_data = hoedown_calloc(*columns, sizeof(hoedown_tableflags));
|
||||||
|
|
||||||
/* Parse the header underline */
|
/* Parse the header underline */
|
||||||
i++;
|
i++;
|
||||||
|
@ -2299,7 +2291,7 @@ parse_table(
|
||||||
hoedown_buffer *body_work = 0;
|
hoedown_buffer *body_work = 0;
|
||||||
|
|
||||||
size_t columns;
|
size_t columns;
|
||||||
int *col_data = NULL;
|
hoedown_tableflags *col_data = NULL;
|
||||||
|
|
||||||
header_work = newbuf(doc, BUFFER_SPAN);
|
header_work = newbuf(doc, BUFFER_SPAN);
|
||||||
body_work = newbuf(doc, BUFFER_BLOCK);
|
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);
|
hoedown_buffer_put(contents, data + start + ind, i - start - ind);
|
||||||
/* add carriage return */
|
/* add carriage return */
|
||||||
if (i < end) {
|
if (i < end) {
|
||||||
hoedown_buffer_put(contents, "\n", 1);
|
hoedown_buffer_putc(contents, '\n');
|
||||||
if (i < end && (data[i] == '\n' || data[i] == '\r')) {
|
if (i < end && (data[i] == '\n' || data[i] == '\r')) {
|
||||||
i++;
|
i++;
|
||||||
if (i < end && data[i] == '\n' && data[i - 1] == '\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 *
|
||||||
hoedown_document_new(
|
hoedown_document_new(
|
||||||
const hoedown_renderer *renderer,
|
const hoedown_renderer *renderer,
|
||||||
unsigned int extensions,
|
hoedown_extensions extensions,
|
||||||
size_t max_nesting)
|
size_t max_nesting)
|
||||||
{
|
{
|
||||||
hoedown_document *doc = NULL;
|
hoedown_document *doc = NULL;
|
||||||
|
|
||||||
assert(max_nesting > 0 && renderer);
|
assert(max_nesting > 0 && renderer);
|
||||||
|
|
||||||
doc = malloc(sizeof(hoedown_document));
|
doc = hoedown_malloc(sizeof(hoedown_document));
|
||||||
if (!doc)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memcpy(&doc->md, renderer, sizeof(hoedown_renderer));
|
memcpy(&doc->md, renderer, sizeof(hoedown_renderer));
|
||||||
|
|
||||||
hoedown_stack_new(&doc->work_bufs[BUFFER_BLOCK], 4);
|
hoedown_stack_init(&doc->work_bufs[BUFFER_BLOCK], 4);
|
||||||
hoedown_stack_new(&doc->work_bufs[BUFFER_SPAN], 8);
|
hoedown_stack_init(&doc->work_bufs[BUFFER_SPAN], 8);
|
||||||
|
|
||||||
memset(doc->active_char, 0x0, 256);
|
memset(doc->active_char, 0x0, 256);
|
||||||
|
|
||||||
|
@ -2723,7 +2712,7 @@ hoedown_document_new(
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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};
|
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;
|
int footnotes_enabled;
|
||||||
|
|
||||||
text = hoedown_buffer_new(64);
|
text = hoedown_buffer_new(64);
|
||||||
if (!text)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Preallocate enough space for our buffer to avoid expanding while copying */
|
/* 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 */
|
/* reset the references table */
|
||||||
memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
|
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
|
/* Skip a possible UTF-8 BOM, even though the Unicode standard
|
||||||
* discourages having these in UTF-8 documents */
|
* 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;
|
beg += 3;
|
||||||
|
|
||||||
while (beg < doc_size) /* iterating over lines */
|
while (beg < size) /* iterating over lines */
|
||||||
if (footnotes_enabled && is_footnote(document, beg, doc_size, &end, &doc->footnotes_found))
|
if (footnotes_enabled && is_footnote(data, beg, size, &end, &doc->footnotes_found))
|
||||||
beg = end;
|
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;
|
beg = end;
|
||||||
else { /* skipping to the next line */
|
else { /* skipping to the next line */
|
||||||
end = beg;
|
end = beg;
|
||||||
while (end < doc_size && document[end] != '\n' && document[end] != '\r')
|
while (end < size && data[end] != '\n' && data[end] != '\r')
|
||||||
end++;
|
end++;
|
||||||
|
|
||||||
/* adding the line body if present */
|
/* adding the line body if present */
|
||||||
if (end > beg)
|
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 */
|
/* 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');
|
hoedown_buffer_putc(text, '\n');
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
|
@ -2817,38 +2804,36 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
size_t i = 0, mark;
|
||||||
hoedown_buffer *text = hoedown_buffer_new(64);
|
hoedown_buffer *text = hoedown_buffer_new(64);
|
||||||
if (!text)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* reset the references table */
|
/* reset the references table */
|
||||||
memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
|
memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
|
||||||
|
|
||||||
/* first pass: convert all spacing to spaces */
|
/* first pass: expand tabs and process newlines */
|
||||||
hoedown_buffer_grow(text, doc_size);
|
hoedown_buffer_grow(text, size);
|
||||||
while (1) {
|
while (1) {
|
||||||
mark = i;
|
mark = i;
|
||||||
while (i < doc_size && document[i] != '\n' && document[i] != '\r')
|
while (i < size && data[i] != '\n' && data[i] != '\r')
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
expand_tabs(text, document + mark, i - mark);
|
expand_tabs(text, data + mark, i - mark);
|
||||||
|
|
||||||
if (i >= doc_size)
|
if (i >= size)
|
||||||
break;
|
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 */
|
/* 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');
|
hoedown_buffer_putc(text, '\n');
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* second pass: actual rendering */
|
/* 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);
|
parse_inline(ob, doc, text->data, text->size);
|
||||||
|
|
||||||
/* clean-up */
|
/* 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)
|
for (i = 0; i < (size_t)doc->work_bufs[BUFFER_BLOCK].asize; ++i)
|
||||||
hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]);
|
hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]);
|
||||||
|
|
||||||
hoedown_stack_free(&doc->work_bufs[BUFFER_SPAN]);
|
hoedown_stack_reset(&doc->work_bufs[BUFFER_SPAN]);
|
||||||
hoedown_stack_free(&doc->work_bufs[BUFFER_BLOCK]);
|
hoedown_stack_reset(&doc->work_bufs[BUFFER_BLOCK]);
|
||||||
|
|
||||||
free(doc);
|
free(doc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,12 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*********
|
|
||||||
* FLAGS *
|
|
||||||
*********/
|
|
||||||
|
|
||||||
enum hoedown_extensions {
|
/*************
|
||||||
|
* CONSTANTS *
|
||||||
|
*************/
|
||||||
|
|
||||||
|
typedef enum hoedown_extensions {
|
||||||
/* block-level extensions */
|
/* block-level extensions */
|
||||||
HOEDOWN_EXT_TABLES = (1 << 0),
|
HOEDOWN_EXT_TABLES = (1 << 0),
|
||||||
HOEDOWN_EXT_FENCED_CODE = (1 << 1),
|
HOEDOWN_EXT_FENCED_CODE = (1 << 1),
|
||||||
|
@ -35,7 +36,7 @@ enum hoedown_extensions {
|
||||||
|
|
||||||
/* negative flags */
|
/* negative flags */
|
||||||
HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 12)
|
HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 12)
|
||||||
};
|
} hoedown_extensions;
|
||||||
|
|
||||||
#define HOEDOWN_EXT_BLOCK (\
|
#define HOEDOWN_EXT_BLOCK (\
|
||||||
HOEDOWN_EXT_TABLES |\
|
HOEDOWN_EXT_TABLES |\
|
||||||
|
@ -58,30 +59,29 @@ enum hoedown_extensions {
|
||||||
#define HOEDOWN_EXT_NEGATIVE (\
|
#define HOEDOWN_EXT_NEGATIVE (\
|
||||||
HOEDOWN_EXT_DISABLE_INDENTED_CODE )
|
HOEDOWN_EXT_DISABLE_INDENTED_CODE )
|
||||||
|
|
||||||
/* list/listitem flags */
|
typedef enum hoedown_listflags {
|
||||||
enum hoedown_listflags {
|
|
||||||
HOEDOWN_LIST_ORDERED = (1 << 0),
|
HOEDOWN_LIST_ORDERED = (1 << 0),
|
||||||
HOEDOWN_LI_BLOCK = (1 << 1) /* <li> containing block data */
|
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_LEFT = 1,
|
||||||
HOEDOWN_TABLE_ALIGN_RIGHT = 2,
|
HOEDOWN_TABLE_ALIGN_RIGHT = 2,
|
||||||
HOEDOWN_TABLE_ALIGN_CENTER = 3,
|
HOEDOWN_TABLE_ALIGN_CENTER = 3,
|
||||||
HOEDOWN_TABLE_ALIGNMASK = 3,
|
HOEDOWN_TABLE_ALIGNMASK = 3,
|
||||||
HOEDOWN_TABLE_HEADER = 4
|
HOEDOWN_TABLE_HEADER = 4
|
||||||
};
|
} hoedown_tableflags;
|
||||||
|
|
||||||
/* hoedown_autolink - type of autolink */
|
typedef enum hoedown_autolink_type {
|
||||||
enum hoedown_autolink {
|
|
||||||
HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/
|
HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/
|
||||||
HOEDOWN_AUTOLINK_NORMAL, /* normal http/http/ftp/mailto/etc link */
|
HOEDOWN_AUTOLINK_NORMAL, /* normal http/http/ftp/mailto/etc link */
|
||||||
HOEDOWN_AUTOLINK_EMAIL /* e-mail link without explit mailto: */
|
HOEDOWN_AUTOLINK_EMAIL /* e-mail link without explit mailto: */
|
||||||
};
|
} hoedown_autolink_type;
|
||||||
|
|
||||||
/********************
|
|
||||||
* TYPE DEFINITIONS *
|
/*********
|
||||||
********************/
|
* TYPES *
|
||||||
|
*********/
|
||||||
|
|
||||||
/* hoedown_renderer - functions for rendering parsed data */
|
/* hoedown_renderer - functions for rendering parsed data */
|
||||||
struct hoedown_renderer {
|
struct hoedown_renderer {
|
||||||
|
@ -94,17 +94,17 @@ struct hoedown_renderer {
|
||||||
void (*blockhtml)(hoedown_buffer *ob,const hoedown_buffer *text, void *opaque);
|
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 (*header)(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaque);
|
||||||
void (*hrule)(hoedown_buffer *ob, void *opaque);
|
void (*hrule)(hoedown_buffer *ob, void *opaque);
|
||||||
void (*list)(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, unsigned int 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 (*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)(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_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 (*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);
|
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 */
|
/* 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 (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
|
||||||
int (*double_emphasis)(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);
|
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_header)(hoedown_buffer *ob, void *opaque);
|
||||||
void (*doc_footer)(hoedown_buffer *ob, void *opaque);
|
void (*doc_footer)(hoedown_buffer *ob, void *opaque);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct hoedown_renderer hoedown_renderer;
|
typedef struct hoedown_renderer hoedown_renderer;
|
||||||
|
|
||||||
struct hoedown_document;
|
struct hoedown_document;
|
||||||
|
|
||||||
typedef struct hoedown_document 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,
|
const hoedown_renderer *renderer,
|
||||||
unsigned int extensions,
|
hoedown_extensions extensions,
|
||||||
size_t max_nesting);
|
size_t max_nesting
|
||||||
|
) __attribute__ ((malloc));
|
||||||
|
|
||||||
extern void
|
/* hoedown_document_render: render regular Markdown using the document processor */
|
||||||
hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size);
|
void hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size);
|
||||||
|
|
||||||
extern void
|
/* hoedown_document_render_inline: render inline Markdown using the document processor */
|
||||||
hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *document, size_t doc_size);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
136
src/escape.c
136
src/escape.c
|
@ -4,6 +4,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.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:
|
* The following characters will not be escaped:
|
||||||
*
|
*
|
||||||
|
@ -17,7 +22,7 @@
|
||||||
*
|
*
|
||||||
* We asume (lazily) that any RESERVED char that
|
* We asume (lazily) that any RESERVED char that
|
||||||
* appears inside an URL is actually meant to
|
* 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.
|
* component/separator) and hence needs no escaping.
|
||||||
*
|
*
|
||||||
* There are two exceptions: the chacters & (amp)
|
* There are two exceptions: the chacters & (amp)
|
||||||
|
@ -30,58 +35,56 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static const uint8_t HREF_SAFE[UINT8_MAX+1] = {
|
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, 0, 0, 0, 0, 0, 0, 0, 0, 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,
|
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, 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, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 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,
|
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,
|
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 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
|
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";
|
static const char hex_chars[] = "0123456789ABCDEF";
|
||||||
size_t i = 0, org;
|
size_t i = 0, mark;
|
||||||
char hex_str[3];
|
char hex_str[3];
|
||||||
|
|
||||||
hex_str[0] = '%';
|
hex_str[0] = '%';
|
||||||
|
|
||||||
while (i < size) {
|
while (i < size) {
|
||||||
org = i;
|
mark = i;
|
||||||
while (i < size && HREF_SAFE[src[i]] != 0)
|
while (i < size && HREF_SAFE[data[i]] != 0)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (i > org) {
|
/* Optimization for cases when there's nothing to escape */
|
||||||
if (org == 0) {
|
if (mark == 0 && i >= size) {
|
||||||
if (i >= size) {
|
hoedown_buffer_put(ob, data, size);
|
||||||
hoedown_buffer_put(ob, src, size);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (i > mark) {
|
||||||
|
hoedown_buffer_put(ob, data + mark, i - mark);
|
||||||
hoedown_buffer_put(ob, src + org, i - org);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* escaping */
|
/* escaping */
|
||||||
if (i >= size)
|
if (i >= size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (src[i]) {
|
switch (data[i]) {
|
||||||
/* amp appears all the time in URLs, but needs
|
/* amp appears all the time in URLs, but needs
|
||||||
* HTML-entity escaping to be inside an href */
|
* HTML-entity escaping to be inside an href */
|
||||||
case '&':
|
case '&':
|
||||||
HOEDOWN_BUFPUTSL(ob, "&");
|
HOEDOWN_BUFPUTSL(ob, "&");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -91,7 +94,7 @@ hoedown_escape_href(hoedown_buffer *ob, const uint8_t *src, size_t size)
|
||||||
case '\'':
|
case '\'':
|
||||||
HOEDOWN_BUFPUTSL(ob, "'");
|
HOEDOWN_BUFPUTSL(ob, "'");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* the space can be escaped to %20 or a plus
|
/* the space can be escaped to %20 or a plus
|
||||||
* sign. we're going with the generic escape
|
* sign. we're going with the generic escape
|
||||||
* for now. the plus thing is more commonly seen
|
* 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 */
|
/* every other character goes with a %XX escaping */
|
||||||
default:
|
default:
|
||||||
hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
|
hex_str[1] = hex_chars[(data[i] >> 4) & 0xF];
|
||||||
hex_str[2] = hex_chars[src[i] & 0xF];
|
hex_str[2] = hex_chars[data[i] & 0xF];
|
||||||
hoedown_buffer_put(ob, hex_str, 3);
|
hoedown_buffer_put(ob, (uint8_t *)hex_str, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* According to the OWASP rules:
|
* 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] = {
|
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, 0, 0, 0, 0,
|
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,36 +158,30 @@ static const char *HTML_ESCAPES[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
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) {
|
while (1) {
|
||||||
org = i;
|
mark = i;
|
||||||
while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
|
while (i < size && HTML_ESCAPE_TABLE[data[i]] == 0) i++;
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i > org) {
|
/* Optimization for cases where there's nothing to escape */
|
||||||
if (org == 0) {
|
if (mark == 0 && i >= size) {
|
||||||
if (i >= size) {
|
hoedown_buffer_put(ob, data, size);
|
||||||
hoedown_buffer_put(ob, src, size);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
hoedown_buffer_put(ob, src + org, i - org);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* escaping */
|
if (likely(i > mark))
|
||||||
if (i >= size)
|
hoedown_buffer_put(ob, data + mark, i - mark);
|
||||||
break;
|
|
||||||
|
if (i >= size) break;
|
||||||
|
|
||||||
/* The forward slash is only escaped in secure mode */
|
/* The forward slash is only escaped in secure mode */
|
||||||
if (src[i] == '/' && !secure) {
|
if (!secure && data[i] == '/') {
|
||||||
hoedown_buffer_putc(ob, '/');
|
hoedown_buffer_putc(ob, '/');
|
||||||
} else {
|
} else {
|
||||||
hoedown_buffer_puts(ob, HTML_ESCAPES[esc]);
|
hoedown_buffer_puts(ob, HTML_ESCAPES[HTML_ESCAPE_TABLE[data[i]]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
13
src/escape.h
13
src/escape.h
|
@ -9,8 +9,17 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
62
src/html.c
62
src/html.c
|
@ -9,34 +9,34 @@
|
||||||
|
|
||||||
#define USE_XHTML(opt) (opt->flags & HOEDOWN_HTML_USE_XHTML)
|
#define USE_XHTML(opt) (opt->flags & HOEDOWN_HTML_USE_XHTML)
|
||||||
|
|
||||||
int
|
hoedown_html_tag
|
||||||
hoedown_html_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname)
|
hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
int closed = 0;
|
int closed = 0;
|
||||||
|
|
||||||
if (tag_size < 3 || tag_data[0] != '<')
|
if (size < 3 || data[0] != '<')
|
||||||
return HOEDOWN_HTML_TAG_NONE;
|
return HOEDOWN_HTML_TAG_NONE;
|
||||||
|
|
||||||
i = 1;
|
i = 1;
|
||||||
|
|
||||||
if (tag_data[i] == '/') {
|
if (data[i] == '/') {
|
||||||
closed = 1;
|
closed = 1;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < tag_size; ++i, ++tagname) {
|
for (; i < size; ++i, ++tagname) {
|
||||||
if (*tagname == 0)
|
if (*tagname == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (tag_data[i] != *tagname)
|
if (data[i] != *tagname)
|
||||||
return HOEDOWN_HTML_TAG_NONE;
|
return HOEDOWN_HTML_TAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == tag_size)
|
if (i == size)
|
||||||
return HOEDOWN_HTML_TAG_NONE;
|
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 closed ? HOEDOWN_HTML_TAG_CLOSE : HOEDOWN_HTML_TAG_OPEN;
|
||||||
|
|
||||||
return HOEDOWN_HTML_TAG_NONE;
|
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 *
|
* GENERIC RENDERER *
|
||||||
********************/
|
********************/
|
||||||
static int
|
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;
|
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)
|
rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int flags, void *opaque)
|
||||||
{
|
{
|
||||||
if (ob->size) hoedown_buffer_putc(ob, '\n');
|
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);
|
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
|
static void
|
||||||
|
@ -428,7 +428,7 @@ rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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) {
|
if (flags & HOEDOWN_TABLE_HEADER) {
|
||||||
HOEDOWN_BUFPUTSL(ob, "<th");
|
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_BUFPUTSL(ob, "<div class=\"footnotes\">\n");
|
||||||
hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
|
hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
|
||||||
HOEDOWN_BUFPUTSL(ob, "<ol>\n");
|
HOEDOWN_BUFPUTSL(ob, "<ol>\n");
|
||||||
|
|
||||||
if (text)
|
if (text)
|
||||||
hoedown_buffer_put(ob, text->data, text->size);
|
hoedown_buffer_put(ob, text->data, text->size);
|
||||||
|
|
||||||
HOEDOWN_BUFPUTSL(ob, "\n</ol>\n</div>\n");
|
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;
|
size_t i = 0;
|
||||||
int pfound = 0;
|
int pfound = 0;
|
||||||
|
|
||||||
/* insert anchor at the end of first paragraph block */
|
/* insert anchor at the end of first paragraph block */
|
||||||
if (text) {
|
if (text) {
|
||||||
while ((i+3) < text->size) {
|
while ((i+3) < text->size) {
|
||||||
|
@ -514,7 +514,7 @@ rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hoedown_buffer_printf(ob, "\n<li id=\"fn%d\">\n", num);
|
hoedown_buffer_printf(ob, "\n<li id=\"fn%d\">\n", num);
|
||||||
if (pfound) {
|
if (pfound) {
|
||||||
hoedown_buffer_put(ob, text->data, i);
|
hoedown_buffer_put(ob, text->data, i);
|
||||||
|
@ -634,23 +634,15 @@ hoedown_html_toc_renderer_new(int nesting_level)
|
||||||
hoedown_renderer *renderer;
|
hoedown_renderer *renderer;
|
||||||
|
|
||||||
/* Prepare the state pointer */
|
/* Prepare the state pointer */
|
||||||
state = malloc(sizeof(hoedown_html_renderer_state));
|
state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
|
||||||
if (!state)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memset(state, 0x0, sizeof(hoedown_html_renderer_state));
|
memset(state, 0x0, sizeof(hoedown_html_renderer_state));
|
||||||
|
|
||||||
state->toc_data.nesting_level = nesting_level;
|
state->toc_data.nesting_level = nesting_level;
|
||||||
|
|
||||||
/* Prepare the renderer */
|
/* Prepare the renderer */
|
||||||
renderer = malloc(sizeof(hoedown_renderer));
|
renderer = hoedown_malloc(sizeof(hoedown_renderer));
|
||||||
if (!renderer) {
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
|
memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
|
||||||
|
|
||||||
renderer->opaque = state;
|
renderer->opaque = state;
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
@ -658,7 +650,7 @@ hoedown_html_toc_renderer_new(int nesting_level)
|
||||||
hoedown_renderer *
|
hoedown_renderer *
|
||||||
hoedown_html_renderer_new(unsigned int render_flags, int nesting_level)
|
hoedown_html_renderer_new(unsigned int render_flags, int nesting_level)
|
||||||
{
|
{
|
||||||
static const hoedown_renderer cb_default = {
|
static const hoedown_renderer cb_default = {
|
||||||
NULL,
|
NULL,
|
||||||
|
|
||||||
rndr_blockcode,
|
rndr_blockcode,
|
||||||
|
@ -702,27 +694,19 @@ hoedown_html_renderer_new(unsigned int render_flags, int nesting_level)
|
||||||
hoedown_renderer *renderer;
|
hoedown_renderer *renderer;
|
||||||
|
|
||||||
/* Prepare the state pointer */
|
/* Prepare the state pointer */
|
||||||
state = malloc(sizeof(hoedown_html_renderer_state));
|
state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
|
||||||
if (!state)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memset(state, 0x0, sizeof(hoedown_html_renderer_state));
|
memset(state, 0x0, sizeof(hoedown_html_renderer_state));
|
||||||
|
|
||||||
state->flags = render_flags;
|
state->flags = render_flags;
|
||||||
state->toc_data.nesting_level = nesting_level;
|
state->toc_data.nesting_level = nesting_level;
|
||||||
|
|
||||||
/* Prepare the renderer */
|
/* Prepare the renderer */
|
||||||
renderer = malloc(sizeof(hoedown_renderer));
|
renderer = hoedown_malloc(sizeof(hoedown_renderer));
|
||||||
if (!renderer) {
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
|
memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
|
||||||
|
|
||||||
if (render_flags & HOEDOWN_HTML_SKIP_HTML || render_flags & HOEDOWN_HTML_ESCAPE)
|
if (render_flags & HOEDOWN_HTML_SKIP_HTML || render_flags & HOEDOWN_HTML_ESCAPE)
|
||||||
renderer->blockhtml = NULL;
|
renderer->blockhtml = NULL;
|
||||||
|
|
||||||
renderer->opaque = state;
|
renderer->opaque = state;
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
52
src/html.h
52
src/html.h
|
@ -1,17 +1,21 @@
|
||||||
/* html.h - HTML renderer */
|
/* html.h - HTML renderer and utilities */
|
||||||
|
|
||||||
#ifndef HOEDOWN_HTML_H
|
#ifndef HOEDOWN_HTML_H
|
||||||
#define HOEDOWN_HTML_H
|
#define HOEDOWN_HTML_H
|
||||||
|
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
|
/*************
|
||||||
|
* CONSTANTS *
|
||||||
|
*************/
|
||||||
|
|
||||||
|
typedef enum hoedown_html_flags {
|
||||||
HOEDOWN_HTML_SKIP_HTML = (1 << 0),
|
HOEDOWN_HTML_SKIP_HTML = (1 << 0),
|
||||||
HOEDOWN_HTML_ESCAPE = (1 << 1),
|
HOEDOWN_HTML_ESCAPE = (1 << 1),
|
||||||
HOEDOWN_HTML_SAFELINK = (1 << 2),
|
HOEDOWN_HTML_SAFELINK = (1 << 2),
|
||||||
|
@ -19,12 +23,17 @@ typedef enum {
|
||||||
HOEDOWN_HTML_USE_XHTML = (1 << 4)
|
HOEDOWN_HTML_USE_XHTML = (1 << 4)
|
||||||
} hoedown_html_flags;
|
} hoedown_html_flags;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum hoedown_html_tag {
|
||||||
HOEDOWN_HTML_TAG_NONE = 0,
|
HOEDOWN_HTML_TAG_NONE = 0,
|
||||||
HOEDOWN_HTML_TAG_OPEN,
|
HOEDOWN_HTML_TAG_OPEN,
|
||||||
HOEDOWN_HTML_TAG_CLOSE
|
HOEDOWN_HTML_TAG_CLOSE
|
||||||
} hoedown_html_tag;
|
} hoedown_html_tag;
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
* TYPES *
|
||||||
|
*********/
|
||||||
|
|
||||||
struct hoedown_html_renderer_state {
|
struct hoedown_html_renderer_state {
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
|
||||||
|
@ -35,28 +44,39 @@ struct hoedown_html_renderer_state {
|
||||||
int nesting_level;
|
int nesting_level;
|
||||||
} toc_data;
|
} toc_data;
|
||||||
|
|
||||||
unsigned int flags;
|
hoedown_html_flags flags;
|
||||||
|
|
||||||
/* extra callbacks */
|
/* extra callbacks */
|
||||||
void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, void *self);
|
void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, void *self);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct hoedown_html_renderer_state hoedown_html_renderer_state;
|
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_smartypants: process an HTML snippet using SmartyPants for smart punctuation */
|
||||||
hoedown_html_toc_renderer_new(int nesting_level);
|
void hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *data, size_t size);
|
||||||
|
|
||||||
extern void
|
/* hoedown_html_is_tag: checks if data starts with a specific tag, returns the tag type or NONE */
|
||||||
hoedown_html_renderer_free(hoedown_renderer *renderer);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
65
src/stack.c
65
src/stack.c
|
@ -1,25 +1,29 @@
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include "buffer.h"
|
||||||
|
|
||||||
int
|
#include <stdlib.h>
|
||||||
hoedown_stack_new(hoedown_stack *st, size_t initial_size)
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
hoedown_stack_init(hoedown_stack *st, size_t initial_size)
|
||||||
{
|
{
|
||||||
|
assert(st);
|
||||||
|
|
||||||
st->item = NULL;
|
st->item = NULL;
|
||||||
st->size = 0;
|
st->size = st->asize = 0;
|
||||||
st->asize = 0;
|
|
||||||
|
|
||||||
if (!initial_size)
|
if (!initial_size)
|
||||||
initial_size = 8;
|
initial_size = 8;
|
||||||
|
|
||||||
return hoedown_stack_grow(st, initial_size);
|
hoedown_stack_grow(st, initial_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hoedown_stack_free(hoedown_stack *st)
|
hoedown_stack_reset(hoedown_stack *st)
|
||||||
{
|
{
|
||||||
if (!st)
|
assert(st);
|
||||||
return;
|
|
||||||
|
|
||||||
free(st->item);
|
free(st->item);
|
||||||
|
|
||||||
|
@ -28,43 +32,38 @@ hoedown_stack_free(hoedown_stack *st)
|
||||||
st->asize = 0;
|
st->asize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
hoedown_stack_grow(hoedown_stack *st, size_t new_size)
|
hoedown_stack_grow(hoedown_stack *st, size_t neosz)
|
||||||
{
|
{
|
||||||
void **new_st;
|
assert(st);
|
||||||
|
|
||||||
if (st->asize >= new_size)
|
if (st->asize >= neosz)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
new_st = realloc(st->item, new_size * sizeof(void *));
|
st->item = hoedown_realloc(st->item, neosz * sizeof(void *));
|
||||||
if (new_st == NULL)
|
memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *));
|
||||||
return -1;
|
st->asize = neosz;
|
||||||
|
|
||||||
memset(new_st + st->asize, 0x0,
|
if (st->size > neosz)
|
||||||
(new_size - st->asize) * sizeof(void *));
|
st->size = neosz;
|
||||||
|
|
||||||
st->item = new_st;
|
|
||||||
st->asize = new_size;
|
|
||||||
|
|
||||||
if (st->size > new_size)
|
|
||||||
st->size = new_size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
hoedown_stack_push(hoedown_stack *st, void *item)
|
hoedown_stack_push(hoedown_stack *st, void *item)
|
||||||
{
|
{
|
||||||
if (hoedown_stack_grow(st, st->size * 2) < 0)
|
assert(st);
|
||||||
return -1;
|
|
||||||
|
if (st->size >= st->asize)
|
||||||
|
hoedown_stack_grow(st, (st->size + 1) * 2);
|
||||||
|
|
||||||
st->item[st->size++] = item;
|
st->item[st->size++] = item;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
hoedown_stack_pop(hoedown_stack *st)
|
hoedown_stack_pop(hoedown_stack *st)
|
||||||
{
|
{
|
||||||
|
assert(st);
|
||||||
|
|
||||||
if (!st->size)
|
if (!st->size)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -72,8 +71,10 @@ hoedown_stack_pop(hoedown_stack *st)
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
hoedown_stack_top(hoedown_stack *st)
|
hoedown_stack_top(const hoedown_stack *st)
|
||||||
{
|
{
|
||||||
|
assert(st);
|
||||||
|
|
||||||
if (!st->size)
|
if (!st->size)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
37
src/stack.h
37
src/stack.h
|
@ -3,26 +3,47 @@
|
||||||
#ifndef HOEDOWN_STACK_H
|
#ifndef HOEDOWN_STACK_H
|
||||||
#define HOEDOWN_STACK_H
|
#define HOEDOWN_STACK_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
* TYPES *
|
||||||
|
*********/
|
||||||
|
|
||||||
struct hoedown_stack {
|
struct hoedown_stack {
|
||||||
void **item;
|
void **item;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t asize;
|
size_t asize;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct hoedown_stack hoedown_stack;
|
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);
|
* FUNCTIONS *
|
||||||
int hoedown_stack_push(hoedown_stack *, void *);
|
*************/
|
||||||
void *hoedown_stack_pop(hoedown_stack *);
|
|
||||||
void *hoedown_stack_top(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_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,24 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* CONSTANTS *
|
||||||
|
*************/
|
||||||
|
|
||||||
#define HOEDOWN_VERSION "2.0.0"
|
#define HOEDOWN_VERSION "2.0.0"
|
||||||
#define HOEDOWN_VERSION_MAJOR 2
|
#define HOEDOWN_VERSION_MAJOR 2
|
||||||
#define HOEDOWN_VERSION_MINOR 0
|
#define HOEDOWN_VERSION_MINOR 0
|
||||||
#define HOEDOWN_VERSION_REVISION 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue