diff options
-rw-r--r-- | Makefile | 4 | ||||
-rwxr-xr-x | src/array.c | 300 | ||||
-rwxr-xr-x | src/array.h | 147 | ||||
-rw-r--r-- | src/autolink.c | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | src/buffer.c | 362 | ||||
-rw-r--r--[-rwxr-xr-x] | src/buffer.h | 167 | ||||
-rw-r--r--[-rwxr-xr-x] | src/markdown.c | 213 | ||||
-rw-r--r--[-rwxr-xr-x] | src/markdown.h | 0 |
8 files changed, 382 insertions, 815 deletions
@@ -32,12 +32,12 @@ all: libsundown.so sundown smartypants html_blocks libsundown.so: libsundown.so.1 ln -f -s $^ $@ -libsundown.so.1: src/markdown.o src/array.o src/buffer.o src/autolink.o html/html.o html/html_smartypants.o +libsundown.so.1: src/markdown.o src/stack.o src/buffer.o src/autolink.o html/html.o html/html_smartypants.o $(CC) $(LDFLAGS) -shared -Wl $^ -o $@ # executables -sundown: examples/sundown.o src/markdown.o src/array.o src/autolink.o src/buffer.o html/html.o html/html_smartypants.o +sundown: examples/sundown.o src/markdown.o src/stack.o src/autolink.o src/buffer.o html/html.o html/html_smartypants.o $(CC) $(LDFLAGS) $^ -o $@ smartypants: examples/smartypants.o src/buffer.o html/html_smartypants.o html/html.o src/autolink.o diff --git a/src/array.c b/src/array.c deleted file mode 100755 index be7a816..0000000 --- a/src/array.c +++ /dev/null @@ -1,300 +0,0 @@ -/* array.c - automatic dynamic array for pointers */ - -/* - * Copyright (c) 2008, Natacha Porté - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "array.h" - -#include <string.h> - - -/*************************** - * STATIC HELPER FUNCTIONS * - ***************************/ - -/* arr_realloc • realloc memory of a struct array */ -static int -arr_realloc(struct array* arr, int neosz) { - void* neo; - neo = realloc(arr->base, neosz * arr->unit); - if (neo == 0) return 0; - arr->base = neo; - arr->asize = neosz; - if (arr->size > neosz) arr->size = neosz; - return 1; } - - -/* parr_realloc • realloc memory of a struct parray */ -static int -parr_realloc(struct parray* arr, int neosz) { - void* neo; - neo = realloc(arr->item, neosz * sizeof (void*)); - if (neo == 0) return 0; - arr->item = neo; - arr->asize = neosz; - if (arr->size > neosz) arr->size = neosz; - return 1; } - - - -/*************************** - * GENERIC ARRAY FUNCTIONS * - ***************************/ - -/* arr_adjust • shrink the allocated memory to fit exactly the needs */ -int -arr_adjust(struct array *arr) { - return arr_realloc(arr, arr->size); } - - -/* arr_free • frees the structure contents (buf NOT the struct itself) */ -void -arr_free(struct array *arr) { - if (!arr) return; - free(arr->base); - arr->base = 0; - arr->size = arr->asize = 0; } - - -/* arr_grow • increases the array size to fit the given number of elements */ -int -arr_grow(struct array *arr, int need) { - if (arr->asize >= need) return 1; - else return arr_realloc(arr, need); } - - -/* arr_init • initialization of the contents of the struct */ -void -arr_init(struct array *arr, size_t unit) { - arr->base = 0; - arr->size = arr->asize = 0; - arr->unit = unit; } - - -/* arr_insert • inserting nb elements before the nth one */ -int -arr_insert(struct array *arr, int nb, int n) { - char *src, *dst; - size_t len; - if (!arr || nb <= 0 || n < 0 - || !arr_grow(arr, arr->size + nb)) - return 0; - if (n < arr->size) { - src = arr->base; - src += n * arr->unit; - dst = src + nb * arr->unit; - len = (arr->size - n) * arr->unit; - memmove(dst, src, len); } - arr->size += nb; - return 1; } - - -/* arr_item • returns a pointer to the n-th element */ -void * -arr_item(struct array *arr, int no) { - char *ptr; - if (!arr || no < 0 || no >= arr->size) return 0; - ptr = arr->base; - ptr += no * arr->unit; - return ptr; } - - -/* arr_newitem • returns the index of a new element appended to the array */ -int -arr_newitem(struct array *arr) { - if (!arr_grow(arr, arr->size + 1)) return -1; - arr->size += 1; - return arr->size - 1; } - - -/* arr_remove • removes the n-th elements of the array */ -void -arr_remove(struct array *arr, int idx) { - if (!arr || idx < 0 || idx >= arr->size) return; - arr->size -= 1; - if (idx < arr->size) { - char *dst = arr->base; - char *src; - dst += idx * arr->unit; - src = dst + arr->unit; - memmove(dst, src, (arr->size - idx) * arr->unit); } } - - -/* arr_sorted_find • O(log n) search in a sorted array, returning entry */ -void * -arr_sorted_find(struct array *arr, void *key, array_cmp_fn cmp) { - int mi, ma, cu, ret; - char *ptr = arr->base; - mi = -1; - ma = arr->size; - while (mi < ma - 1) { - cu = mi + (ma - mi) / 2; - ret = cmp(key, ptr + cu * arr->unit); - if (ret == 0) return ptr + cu * arr->unit; - else if (ret < 0) ma = cu; - else /* if (ret > 0) */ mi = cu; } - return 0; } - - -/* arr_sorted_find_i • O(log n) search in a sorted array, - * returning index of the smallest element larger than the key */ -int -arr_sorted_find_i(struct array *arr, void *key, array_cmp_fn cmp) { - int mi, ma, cu, ret; - char *ptr = arr->base; - mi = -1; - ma = arr->size; - while (mi < ma - 1) { - cu = mi + (ma - mi) / 2; - ret = cmp(key, ptr + cu * arr->unit); - if (ret == 0) { - while (cu < arr->size && ret == 0) { - cu += 1; - ret = cmp(key, ptr + cu * arr->unit); } - return cu; } - else if (ret < 0) ma = cu; - else /* if (ret > 0) */ mi = cu; } - return ma; } - - - -/*************************** - * POINTER ARRAY FUNCTIONS * - ***************************/ - -/* parr_adjust • shrinks the allocated memory to fit exactly the needs */ -int -parr_adjust(struct parray* arr) { - return parr_realloc (arr, arr->size); } - - -/* parr_free • frees the structure contents (buf NOT the struct itself) */ -void -parr_free(struct parray *arr) { - if (!arr) return; - free (arr->item); - arr->item = 0; - arr->size = 0; - arr->asize = 0; } - - -/* parr_grow • increases the array size to fit the given number of elements */ -int -parr_grow(struct parray *arr, int need) { - if (arr->asize >= need) return 1; - else return parr_realloc (arr, need); } - - -/* parr_init • initialization of the struct (which is equivalent to zero) */ -void -parr_init(struct parray *arr) { - arr->item = 0; - arr->size = 0; - arr->asize = 0; } - - -/* parr_insert • inserting nb elements before the nth one */ -int -parr_insert(struct parray *parr, int nb, int n) { - char *src, *dst; - size_t len, i; - if (!parr || nb <= 0 || n < 0 - || !parr_grow(parr, parr->size + nb)) - return 0; - if (n < parr->size) { - src = (void *)parr->item; - src += n * sizeof (void *); - dst = src + nb * sizeof (void *); - len = (parr->size - n) * sizeof (void *); - memmove(dst, src, len); - for (i = 0; i < (size_t)nb; ++i) - parr->item[n + i] = 0; } - parr->size += nb; - return 1; } - - -/* parr_pop • pops the last item of the array and returns it */ -void * -parr_pop(struct parray *arr) { - if (arr->size <= 0) return 0; - arr->size -= 1; - return arr->item[arr->size]; } - - -/* parr_push • pushes a pointer at the end of the array (= append) */ -int -parr_push(struct parray *arr, void *i) { - if (!parr_grow(arr, arr->size + 1)) return 0; - arr->item[arr->size] = i; - arr->size += 1; - return 1; } - - -/* parr_remove • removes the n-th element of the array and returns it */ -void * -parr_remove(struct parray *arr, int idx) { - void* ret; - int i; - if (!arr || idx < 0 || idx >= arr->size) return 0; - ret = arr->item[idx]; - for (i = idx+1; i < arr->size; ++i) - arr->item[i - 1] = arr->item[i]; - arr->size -= 1; - return ret; } - - -/* parr_sorted_find • O(log n) search in a sorted array, returning entry */ -void * -parr_sorted_find(struct parray *arr, void *key, array_cmp_fn cmp) { - int mi, ma, cu, ret; - mi = -1; - ma = arr->size; - while (mi < ma - 1) { - cu = mi + (ma - mi) / 2; - ret = cmp(key, arr->item[cu]); - if (ret == 0) return arr->item[cu]; - else if (ret < 0) ma = cu; - else /* if (ret > 0) */ mi = cu; } - return 0; } - - -/* parr_sorted_find_i • O(log n) search in a sorted array, - * returning index of the smallest element larger than the key */ -int -parr_sorted_find_i(struct parray *arr, void *key, array_cmp_fn cmp) { - int mi, ma, cu, ret; - mi = -1; - ma = arr->size; - while (mi < ma - 1) { - cu = mi + (ma - mi) / 2; - ret = cmp(key, arr->item[cu]); - if (ret == 0) { - while (cu < arr->size && ret == 0) { - cu += 1; - ret = cmp(key, arr->item[cu]); } - return cu; } - else if (ret < 0) ma = cu; - else /* if (ret > 0) */ mi = cu; } - return ma; } - - -/* parr_top • returns the top the stack (i.e. the last element of the array) */ -void * -parr_top(struct parray *arr) { - if (arr == 0 || arr->size <= 0) return 0; - else return arr->item[arr->size - 1]; } - -/* vim: set filetype=c: */ diff --git a/src/array.h b/src/array.h deleted file mode 100755 index bb9a2a5..0000000 --- a/src/array.h +++ /dev/null @@ -1,147 +0,0 @@ -/* array.h - automatic dynamic array for pointers */ - -/* - * Copyright (c) 2008, Natacha Porté - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef LITHIUM_ARRAY_H -#define LITHIUM_ARRAY_H - -#include <stdlib.h> - -/******************** - * TYPE DEFINITIONS * - ********************/ - -/* struct array • generic linear array */ -struct array { - void* base; - int size; - int asize; - size_t unit; }; - - -/* struct parray • array of pointers */ -struct parray { - void ** item; - int size; - int asize; }; - - -/* array_cmp_fn • comparison functions for sorted arrays */ -typedef int (*array_cmp_fn)(void *key, void *array_entry); - - - -/*************************** - * GENERIC ARRAY FUNCTIONS * - ***************************/ - -/* arr_adjust • shrink the allocated memory to fit exactly the needs */ -int -arr_adjust(struct array *); - -/* arr_free • frees the structure contents (buf NOT the struct itself) */ -void -arr_free(struct array *); - -/* arr_grow • increases the array size to fit the given number of elements */ -int -arr_grow(struct array *, int); - -/* arr_init • initialization of the contents of the struct */ -void -arr_init(struct array *, size_t); - -/* arr_insert • inserting elements nb before the nth one */ -int -arr_insert(struct array *, int nb, int n); - -/* arr_item • returns a pointer to the n-th element */ -void * -arr_item(struct array *, int); - -/* arr_newitem • returns the index of a new element appended to the array */ -int -arr_newitem(struct array *); - -/* arr_remove • removes the n-th elements of the array */ -void -arr_remove(struct array *, int); - -/* arr_sorted_find • O(log n) search in a sorted array, returning entry */ -/* equivalent to bsearch(key, arr->base, arr->size, arr->unit, cmp) */ -void * -arr_sorted_find(struct array *, void *key, array_cmp_fn cmp); - -/* arr_sorted_find_i • O(log n) search in a sorted array, - * returning index of the smallest element larger than the key */ -int -arr_sorted_find_i(struct array *, void *key, array_cmp_fn cmp); - - -/*************************** - * POINTER ARRAY FUNCTIONS * - ***************************/ - -/* parr_adjust • shrinks the allocated memory to fit exactly the needs */ -int -parr_adjust(struct parray *); - -/* parr_free • frees the structure contents (buf NOT the struct itself) */ -void -parr_free(struct parray *); - -/* parr_grow • increases the array size to fit the given number of elements */ -int -parr_grow(struct parray *, int); - -/* parr_init • initialization of the struct (which is equivalent to zero) */ -void -parr_init(struct parray *); - -/* parr_insert • inserting nb elements before the nth one */ -int -parr_insert(struct parray *, int nb, int n); - -/* parr_pop • pops the last item of the array and returns it */ -void * -parr_pop(struct parray *); - -/* parr_push • pushes a pointer at the end of the array (= append) */ -int -parr_push(struct parray *, void *); - -/* parr_remove • removes the n-th element of the array and returns it */ -void * -parr_remove(struct parray *, int); - -/* parr_sorted_find • O(log n) search in a sorted array, returning entry */ -void * -parr_sorted_find(struct parray *, void *key, array_cmp_fn cmp); - -/* parr_sorted_find_i • O(log n) search in a sorted array, - * returning index of the smallest element larger than the key */ -int -parr_sorted_find_i(struct parray *, void *key, array_cmp_fn cmp); - -/* parr_top • returns the top the stack (i.e. the last element of the array) */ -void * -parr_top(struct parray *); - - -#endif /* ndef LITHIUM_ARRAY_H */ - -/* vim: set filetype=c: */ diff --git a/src/autolink.c b/src/autolink.c index b31658a..02ea9cd 100644 --- a/src/autolink.c +++ b/src/autolink.c @@ -154,7 +154,7 @@ sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1])) return 0; - if (size < 4 || memcmp(data, "www.", STRLEN("www.")) != 0) + if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0) return 0; link_end = check_domain(data, size); @@ -238,7 +238,7 @@ sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, if (!sd_autolink_issafe(data - rewind, size + rewind)) return 0; - link_end = STRLEN("://"); + link_end = strlen("://"); domain_len = check_domain(data + link_end, size - link_end); if (domain_len == 0) diff --git a/src/buffer.c b/src/buffer.c index 4b04a78..1098eaf 100755..100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,7 +1,6 @@ -/* buffer.c - automatic buffer structure */ - /* * Copyright (c) 2008, Natacha Porté + * Copyright (c) 2011, Vicent Martí * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,13 +15,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* - * COMPILE TIME OPTIONS - * - * BUFFER_STATS • if defined, stats are kept about memory usage - */ - -#define BUFFER_STDARG #define BUFFER_MAX_ALLOC_SIZE (1024 * 1024 * 16) //16mb #include "buffer.h" @@ -31,77 +23,64 @@ #include <stdlib.h> #include <string.h> - -/******************** - * GLOBAL VARIABLES * - ********************/ - -#ifdef BUFFER_STATS -long buffer_stat_nb = 0; -size_t buffer_stat_alloc_bytes = 0; +/* MSVC compat */ +#if defined(_MSC_VER) +# define _buf_vsnprintf _vsnprintf +#else +# define _buf_vsnprintf vsnprintf #endif +/* bufcmp: buffer comparison */ +int +bufcmp(const struct buf *a, const struct buf *b) +{ + size_t i = 0; + size_t cmplen; -/*************************** - * STATIC HELPER FUNCTIONS * - ***************************/ - -/* lower • retruns the lower-case variant of the input char */ -static char -lower(char c) { - return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; } - + if (a == b) + return 0; + if (!a) + return -1; -/******************** - * BUFFER FUNCTIONS * - ********************/ + if (!b) + return 1; -/* bufcasecmp • case-insensitive buffer comparison */ -int -bufcasecmp(const struct buf *a, const struct buf *b) { - size_t i = 0; - size_t cmplen; - if (a == b) return 0; - if (!a) return -1; else if (!b) return 1; cmplen = (a->size < b->size) ? a->size : b->size; - while (i < cmplen && lower(a->data[i]) == lower(b->data[i])) ++i; - if (i < a->size) { - if (i < b->size) return lower(a->data[i]) - lower(b->data[i]); - else return 1; } - else { if (i < b->size) return -1; - else return 0; } } + while (i < cmplen && a->data[i] == b->data[i]) + ++i; -/* bufcmp • case-sensitive buffer comparison */ -int -bufcmp(const struct buf *a, const struct buf *b) { - size_t i = 0; - size_t cmplen; - if (a == b) return 0; - if (!a) return -1; else if (!b) return 1; - cmplen = (a->size < b->size) ? a->size : b->size; - while (i < cmplen && a->data[i] == b->data[i]) ++i; if (i < a->size) { - if (i < b->size) return a->data[i] - b->data[i]; - else return 1; } - else { if (i < b->size) return -1; - else return 0; } } - + if (i < b->size) return a->data[i] - b->data[i]; + return 1; + } else { + if (i < b->size) return -1; + return 0; + } +} -/* bufcmps • case-sensitive comparison of a string to a buffer */ +/* bufcmps: comparison of a string to a buffer */ int -bufcmps(const struct buf *a, const char *b) { +bufcmps(const struct buf *a, const char *b) +{ const size_t len = strlen(b); size_t cmplen = len; int r; - if (!a || !a->size) return b ? 0 : -1; - if (len < a->size) cmplen = a->size; + + if (!a || !a->size) + return b ? 0 : -1; + + if (len < a->size) + cmplen = a->size; + r = strncmp(a->data, b, cmplen); + if (r) return r; else if (a->size == len) return 0; else if (a->size < len) return -1; - else return 1; } + else return 1; +} int bufprefix(const struct buf *buf, const char *prefix) @@ -120,199 +99,231 @@ bufprefix(const struct buf *buf, const char *prefix) } -/* bufdup • buffer duplication */ +/* bufdup: buffer duplication */ struct buf * -bufdup(const struct buf *src, size_t dupunit) { +bufdup(const struct buf *src, size_t dupunit) +{ size_t blocks; struct buf *ret; - if (src == 0) return 0; + if (src == 0) + return 0; + ret = malloc(sizeof (struct buf)); - if (ret == 0) return 0; + if (ret == 0) + return 0; + ret->unit = dupunit; ret->size = src->size; ret->ref = 1; if (!src->size) { ret->asize = 0; ret->data = 0; - return ret; } + return ret; + } + blocks = (src->size + dupunit - 1) / dupunit; ret->asize = blocks * dupunit; ret->data = malloc(ret->asize); + if (ret->data == 0) { free(ret); - return 0; } + return 0; + } + memcpy(ret->data, src->data, src->size); -#ifdef BUFFER_STATS - buffer_stat_nb += 1; - buffer_stat_alloc_bytes += ret->asize; -#endif - return ret; } + return ret; +} -/* bufgrow • increasing the allocated size to the given value */ +/* bufgrow: increasing the allocated size to the given value */ int -bufgrow(struct buf *buf, size_t neosz) { +bufgrow(struct buf *buf, size_t neosz) +{ size_t neoasz; void *neodata; - if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE) return 0; - if (buf->asize >= neosz) return 1; + if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE) + return BUF_ENOMEM; + + if (buf->asize >= neosz) + return BUF_OK; + neoasz = buf->asize + buf->unit; - while (neoasz < neosz) neoasz += buf->unit; + while (neoasz < neosz) + neoasz += buf->unit; + neodata = realloc(buf->data, neoasz); - if (!neodata) return 0; -#ifdef BUFFER_STATS - buffer_stat_alloc_bytes += (neoasz - buf->asize); -#endif + if (!neodata) + return BUF_ENOMEM; + buf->data = neodata; buf->asize = neoasz; - return 1; } + return BUF_OK; +} -/* bufnew • allocation of a new buffer */ +/* bufnew: allocation of a new buffer */ struct buf * -bufnew(size_t unit) { +bufnew(size_t unit) +{ struct buf *ret; ret = malloc(sizeof (struct buf)); + if (ret) { -#ifdef BUFFER_STATS - buffer_stat_nb += 1; -#endif ret->data = 0; ret->size = ret->asize = 0; ret->ref = 1; - ret->unit = unit; } - return ret; } + ret->unit = unit; + } + return ret; +} +/* bufnullterm: NULL-termination of the string array */ +const char * +bufcstr(struct buf *buf) +{ + if (!buf || !buf->unit) + return NULL; -/* bufnullterm • NUL-termination of the string array (making a C-string) */ -void -bufnullterm(struct buf *buf) { - if (!buf || !buf->unit) return; - if (buf->size < buf->asize && buf->data[buf->size] == 0) return; - if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1)) - buf->data[buf->size] = 0; } + if (buf->size < buf->asize && buf->data[buf->size] == 0) + return buf->data; + if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) { + buf->data[buf->size] = 0; + return buf->data; + } + + return NULL; +} -/* bufprintf • formatted printing to a buffer */ +/* bufprintf: formatted printing to a buffer */ void -bufprintf(struct buf *buf, const char *fmt, ...) { +bufprintf(struct buf *buf, const char *fmt, ...) +{ va_list ap; - if (!buf || !buf->unit) return; + if (!buf || !buf->unit) + return; + va_start(ap, fmt); vbufprintf(buf, fmt, ap); - va_end(ap); } - + va_end(ap); +} -/* bufput • appends raw data to a buffer */ +/* bufput: appends raw data to a buffer */ void -bufput(struct buf *buf, const void *data, size_t len) { - if (!buf) return; - if (buf->size + len > buf->asize && !bufgrow(buf, buf->size + len)) +bufput(struct buf *buf, const void *data, size_t len) +{ + if (!buf) return; - memcpy(buf->data + buf->size, data, len); - buf->size += len; } + if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0) + return; + + memcpy(buf->data + buf->size, data, len); + buf->size += len; +} -/* bufputs • appends a NUL-terminated string to a buffer */ +/* bufputs: appends a NUL-terminated string to a buffer */ void -bufputs(struct buf *buf, const char *str) { - bufput(buf, str, strlen (str)); } +bufputs(struct buf *buf, const char *str) +{ + bufput(buf, str, strlen(str)); +} -/* bufputc • appends a single char to a buffer */ +/* bufputc: appends a single char to a buffer */ void -bufputc(struct buf *buf, char c) { - if (!buf) return; - if (buf->size + 1 > buf->asize && !bufgrow(buf, buf->size + 1)) +bufputc(struct buf *buf, char c) +{ + if (!buf) return; - buf->data[buf->size] = c; - buf->size += 1; } + if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0) + return; -/* bufrelease • decrease the reference count and free the buffer if needed */ + buf->data[buf->size] = c; + buf->size += 1; +} + +/* bufrelease: decrease the reference count and free the buffer if needed */ void -bufrelease(struct buf *buf) { - if (!buf) return; - buf->ref -= 1; - if (buf->ref == 0) { -#ifdef BUFFER_STATS - buffer_stat_nb -= 1; - buffer_stat_alloc_bytes -= buf->asize; -#endif +bufrelease(struct buf *buf) +{ + if (!buf) + return; + + if (--buf->ref == 0) { free(buf->data); - free(buf); } } + free(buf); + } +} -/* bufreset • frees internal data of the buffer */ +/* bufreset: frees internal data of the buffer */ void -bufreset(struct buf *buf) { - if (!buf) return; -#ifdef BUFFER_STATS - buffer_stat_alloc_bytes -= buf->asize; -#endif +bufreset(struct buf *buf) +{ + if (!buf) + return; + free(buf->data); - buf->data = 0; - buf->size = buf->asize = 0; } + buf->data = NULL; + buf->size = buf->asize = 0; +} -/* bufset • safely assigns a buffer to another */ +/* bufset: safely assigns a buffer to another */ void -bufset(struct buf **dest, struct buf *src) { +bufset(struct buf **dest, struct buf *src) +{ if (src) { if (!src->asize) src = bufdup(src, 1); - else src->ref += 1; } - bufrelease(*dest); - *dest = src; } + else src->ref += 1; + } + bufrelease(*dest); + *dest = src; +} -/* bufslurp • removes a given number of bytes from the head of the array */ +/* bufslurp: removes a given number of bytes from the head of the array */ void -bufslurp(struct buf *buf, size_t len) { - if (!buf || !buf->unit || len <= 0) return; +bufslurp(struct buf *buf, size_t len) +{ + if (!buf || !buf->unit || len <= 0) + return; + if (len >= buf->size) { buf->size = 0; - return; } - buf->size -= len; - memmove(buf->data, buf->data + len, buf->size); } + return; + } + buf->size -= len; + memmove(buf->data, buf->data + len, buf->size); +} -/* buftoi • converts the numbers at the beginning of the buf into an int */ -int -buftoi(struct buf *buf, size_t offset_i, size_t *offset_o) { - int r = 0, neg = 0; - size_t i = offset_i; - if (!buf || !buf->size) return 0; - if (buf->data[i] == '+') i += 1; - else if (buf->data[i] == '-') { - neg = 1; - i += 1; } - while (i < buf->size && buf->data[i] >= '0' && buf->data[i] <= '9') { - r = (r * 10) + buf->data[i] - '0'; - i += 1; } - if (offset_o) *offset_o = i; - return neg ? -r : r; } - - - -/* vbufprintf • stdarg variant of formatted printing into a buffer */ +/* vbufprintf: stdarg variant of formatted printing into a buffer */ void -vbufprintf(struct buf *buf, const char *fmt, va_list ap) { +vbufprintf(struct buf *buf, const char *fmt, va_list ap) +{ int n; - va_list ap_save; - if (buf == 0 - || (buf->size >= buf->asize && !bufgrow (buf, buf->size + 1))) + + if (buf == 0 || (buf->size >= buf->asize && bufgrow(buf, buf->size + 1)) < 0) return; - va_copy(ap_save, ap); - n = vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap); + n = _buf_vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap); + + if (n < 0) { +#ifdef _MSC_VER + n = _vscprintf(fmt, ap); +#else + return; +#endif + } - if (n < 0 || (size_t)n >= buf->asize - buf->size) { - size_t new_size = (n > 0) ? n : buf->size; - if (!bufgrow (buf, buf->size + new_size + 1)) + if ((size_t)n >= buf->asize - buf->size) { + if (bufgrow(buf, buf->size + n + 1) < 0) return; - n = vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap_save); + n = _buf_vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap); } - va_end(ap_save); if (n < 0) return; @@ -320,4 +331,3 @@ vbufprintf(struct buf *buf, const char *fmt, va_list ap) { buf->size += n; } -/* vim: set filetype=c: */ diff --git a/src/buffer.h b/src/buffer.h index ea0ad65..6db4d78 100755..100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1,7 +1,6 @@ -/* buffer.h - automatic buffer structure */ - /* * Copyright (c) 2008, Natacha Porté + * Copyright (c) 2011, Vicent Martí * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,139 +15,89 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef LITHIUM_BUFFER_H -#define LITHIUM_BUFFER_H +#ifndef __GEN_BUFFER_H__ +#define __GEN_BUFFER_H__ #include <stddef.h> +#include <stdarg.h> #if defined(_MSC_VER) #define __attribute__(x) #define inline -#define strncasecmp _strnicmp -#define snprintf _snprintf -#define va_copy(d,s) ((d) = (s)) #endif -/******************** - * TYPE DEFINITIONS * - ********************/ +typedef enum { + BUF_OK = 0, + BUF_ENOMEM = -1, +} buferror_t; -/* struct buf • character array buffer */ +/* struct buf: character array buffer */ struct buf { - char * data; /* actual character data */ - size_t size; /* size of the string */ - size_t asize; /* allocated size (0 = volatile buffer) */ - size_t unit; /* reallocation unit size (0 = read-only buffer) */ - int ref; }; /* reference count */ - -/********** - * MACROS * - **********/ - -#define STRLEN(x) (sizeof(x) - 1) - -/* CONST_BUF • global buffer from a string litteral */ -#define CONST_BUF(name, string) \ - static struct buf name = { string, sizeof string -1, sizeof string } - - -/* VOLATILE_BUF • macro for creating a volatile buffer on the stack */ -#define VOLATILE_BUF(name, strname) \ - struct buf name = { strname, strlen(strname) } - - -/* BUFPUTSL • optimized bufputs of a string litteral */ + char *data; /* actual character data */ + size_t size; /* size of the string */ + size_t asize; /* allocated size (0 = volatile buffer) */ + size_t unit; /* reallocation unit size (0 = read-only buffer) */ + int ref; /* reference count */ +}; + +/* CONST_BUF: global buffer from a string litteral */ +#define BUF_STATIC(string) \ + { string, sizeof string -1, sizeof string, 0, 0 } + +/* VOLATILE_BUF: macro for creating a volatile buffer on the stack */ +#define BUF_VOLATILE(strname) \ + { strname, strlen(strname), 0, 0, 0 } + +/* BUFPUTSL: optimized bufputs of a string litteral */ #define BUFPUTSL(output, litteral) \ bufput(output, litteral, sizeof litteral - 1) +/* bufcmp: case-sensitive buffer comparison */ +int bufcmp(const struct buf *, const struct buf *); +/* bufcmps: case-sensitive comparison of a string to a buffer */ +int bufcmps(const struct buf *, const char *); -/******************** - * BUFFER FUNCTIONS * - ********************/ - -/* bufcasecmp • case-insensitive buffer comparison */ -int -bufcasecmp(const struct buf *, const struct buf *); - -/* bufcmp • case-sensitive buffer comparison */ -int -bufcmp(const struct buf *, const struct buf *); +/* bufprefix: compare the beginning of a buffer with a string */ +int bufprefix(const struct buf *buf, const char *prefix); -/* bufcmps • case-sensitive comparison of a string to a buffer */ -int -bufcmps(const struct buf *, const char *); +/* bufdup: buffer duplication */ +struct buf *bufdup(const struct buf *, size_t) __attribute__ ((malloc)); -/* bufprefix * compare the beginning of a buffer with a string */ -int -bufprefix(const struct buf *buf, const char *prefix); +/* bufgrow: increasing the allocated size to the given value */ +int bufgrow(struct buf *, size_t); -/* bufdup • buffer duplication */ -struct buf * -bufdup(const struct buf *, size_t) - __attribute__ ((malloc)); +/* bufnew: allocation of a new buffer */ +struct buf *bufnew(size_t) __attribute__ ((malloc)); -/* bufgrow • increasing the allocated size to the given value */ -int -bufgrow(struct buf *, size_t); +/* bufnullterm: NUL-termination of the string array (making a C-string) */ +const char *bufcstr(struct buf *); -/* bufnew • allocation of a new buffer */ -struct buf * -bufnew(size_t) - __attribute__ ((malloc)); +/* bufprintf: formatted printing to a buffer */ +void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3))); -/* bufnullterm • NUL-termination of the string array (making a C-string) */ -void -bufnullterm(struct buf *); +/* bufput: appends raw data to a buffer */ +void bufput(struct buf *, const void*, size_t); -/* bufprintf • formatted printing to a buffer */ -void -bufprintf(struct buf *, const char *, ...) - __attribute__ ((format (printf, 2, 3))); +/* bufputs: appends a NUL-terminated string to a buffer */ +void bufputs(struct buf *, const char*); -/* bufput • appends raw data to a buffer */ -void -bufput(struct buf *, const void*, size_t); +/* bufputc: appends a single char to a buffer */ +void bufputc(struct buf *, char); -/* bufputs • appends a NUL-terminated string to a buffer */ -void -bufputs(struct buf *, const char*); +/* bufrelease: decrease the reference count and free the buffer if needed */ +void bufrelease(struct buf *); -/* bufputc • appends a single char to a buffer */ -void -bufputc(struct buf *, char); +/* bufreset: frees internal data of the buffer */ +void bufreset(struct buf *); -/* bufrelease • decrease the reference count and free the buffer if needed */ -void -bufrelease(struct buf *); +/* bufset: safely assigns a buffer to another */ +void bufset(struct buf **, struct buf *); -/* bufreset • frees internal data of the buffer */ -void -bufreset(struct buf *); +/* bufslurp: removes a given number of bytes from the head of the array */ +void bufslurp(struct buf *, size_t); -/* bufset • safely assigns a buffer to another */ -void -bufset(struct buf **, struct buf *); +/* vbufprintf: stdarg variant of formatted printing into a buffer */ +void vbufprintf(struct buf *, const char*, va_list); -/* bufslurp • removes a given number of bytes from the head of the array */ -void -bufslurp(struct buf *, size_t); - -/* buftoi • converts the numbers at the beginning of the buf into an int */ -int -buftoi(struct buf *, size_t, size_t *); - - - -#ifdef BUFFER_STDARG -#include <stdarg.h> - -/* vbufprintf • stdarg variant of formatted printing into a buffer */ -void -vbufprintf(struct buf *, const char*, va_list); - -#endif /* def BUFFER_STDARG */ - -#endif /* ndef LITHIUM_BUFFER_H */ - -/* vim: set filetype=c: */ +#endif diff --git a/src/markdown.c b/src/markdown.c index f769a8b..ee19009 100755..100644 --- a/src/markdown.c +++ b/src/markdown.c @@ -18,14 +18,15 @@ */ #include "markdown.h" -#include "array.h" +#include "stack.h" #include <assert.h> #include <string.h> -//#include <strings.h> /* for strncasecmp */ #include <ctype.h> #include <stdio.h> +#define REF_TABLE_SIZE 8 + #define BUFFER_BLOCK 0 #define BUFFER_SPAN 1 @@ -40,14 +41,17 @@ * LOCAL TYPES * ***************/ -/* link_ref • reference to a link */ +/* link_ref: reference to a link */ struct link_ref { - struct buf *id; - struct buf *link; - struct buf *title; + unsigned int id; + + struct buf link; + struct buf title; + + struct link_ref *next; }; -/* char_trigger • function pointer to render active chars */ +/* char_trigger: function pointer to render active chars */ /* returns the number of chars taken care of */ /* data is the pointer of the beginning of the span */ /* offset is the number of valid chars before data */ @@ -102,9 +106,9 @@ struct render { struct sd_callbacks cb; void *opaque; - struct array refs; + struct link_ref *refs[REF_TABLE_SIZE]; char active_char[256]; - struct parray work_bufs[2]; + struct stack work_bufs[2]; unsigned int ext_flags; size_t max_nesting; }; @@ -118,14 +122,15 @@ rndr_newbuf(struct render *rndr, int type) { static const size_t buf_size[2] = {256, 64}; struct buf *work = NULL; - struct parray *queue = &rndr->work_bufs[type]; + struct stack *pool = &rndr->work_bufs[type]; - if (queue->size < queue->asize) { - work = queue->item[queue->size++]; + if (pool->size < pool->asize && + pool->item[pool->size] != NULL) { + work = pool->item[pool->size++]; work->size = 0; } else { work = bufnew(buf_size[type]); - parr_push(queue, work); + stack_push(pool, work); } return work; @@ -157,21 +162,72 @@ unscape_text(struct buf *ob, struct buf *src) } } -/* cmp_link_ref • comparison function for link_ref sorted arrays */ -static int -cmp_link_ref(void *key, void *array_entry) +static unsigned int +hash_link_ref(char *link_ref, size_t length) { - struct link_ref *lr = array_entry; - return bufcasecmp(key, lr->id); + size_t i; + unsigned int hash = 0; + + for (i = 0; i < length; ++i) + hash = tolower(link_ref[i]) + (hash << 6) + (hash << 16) - hash; + + return hash; } -/* cmp_link_ref_sort • comparison function for link_ref qsort */ -static int -cmp_link_ref_sort(const void *a, const void *b) +static void add_link_ref( + struct link_ref **references, + char *name, size_t name_size, + char *link, size_t link_size, + char *title, size_t title_size) +{ + struct link_ref *ref = calloc(1, sizeof(struct link_ref)); + + if (!ref) + return; + + ref->id = hash_link_ref(name, name_size); + ref->next = references[ref->id % REF_TABLE_SIZE]; + + ref->link.data = link; + ref->link.size = link_size; + + ref->title.data = title; + ref->title.size = title_size; + + references[ref->id % REF_TABLE_SIZE] = ref; +} + +static struct link_ref * +find_link_ref(struct link_ref **references, char *name, size_t length) { - const struct link_ref *lra = a; - const struct link_ref *lrb = b; - return bufcasecmp(lra->id, lrb->id); + unsigned int hash = hash_link_ref(name, length); + struct link_ref *ref = NULL; + + ref = references[hash % REF_TABLE_SIZE]; + + while (ref != NULL) { + if (ref->id == hash) + return ref; + + ref = ref->next; + } + + return NULL; +} + +static void +free_link_refs(struct link_ref **references) +{ + size_t i; + + for (i = 0; i < REF_TABLE_SIZE; ++i) { + struct link_ref *r = references[i]; + struct link_ref *next; + + while (r) { + next = r->next; free(r); r = next; + } + } } /**************************** @@ -304,10 +360,10 @@ parse_inline(struct buf *ob, struct render *rndr, char *data, size_t size) end = markdown_char_ptrs[(int)action](ob, rndr, data + i, i, size - i); if (!end) /* no action from the callback */ end = i + 1; - else { + else { i += end; end = i; - } + } } } @@ -451,7 +507,7 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c if (!render_method) return 0; - + while (i < size) { len = find_emph_char(data + i, size - i, c); if (!len) return 0; @@ -508,7 +564,7 @@ parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c else return len - 1; } } - return 0; + return 0; } /* char_emphasis • single and double emphasis parsing */ @@ -541,7 +597,7 @@ char_emphasis(struct buf *ob, struct render *rndr, char *data, size_t offset, si return ret + 3; } - return 0; + return 0; } @@ -894,12 +950,14 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t id.size = link_e - link_b; } - lr = arr_sorted_find(&rndr->refs, &id, cmp_link_ref); - if (!lr) goto cleanup; + lr = find_link_ref(rndr->refs, id.data, id.size); + if (!lr) + goto cleanup; /* keeping link and title from link_ref */ - link = lr->link; - title = lr->title; + link = &lr->link; + if (lr->title.size) + title = &lr->title; i++; } @@ -928,12 +986,14 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t } /* finding the link_ref */ - lr = arr_sorted_find(&rndr->refs, &id, cmp_link_ref); - if (!lr) goto cleanup; + lr = find_link_ref(rndr->refs, id.data, id.size); + if (!lr) + goto cleanup; /* keeping link and title from link_ref */ - link = lr->link; - title = lr->title; + link = &lr->link; + if (lr->title.size) + title = &lr->title; /* rewinding the whitespace */ i = txt_e + 1; @@ -1527,7 +1587,7 @@ parse_listitem(struct buf *ob, struct render *rndr, char *data, size_t size, int /* intermediate render of block li */ if (sublist && sublist < work->size) { parse_block(inter, rndr, work->data, sublist); - parse_block(inter, rndr, work->data + sublist, work->size - sublist); + parse_block(inter, rndr, work->data + sublist, work->size - sublist); } else parse_block(inter, rndr, work->data, work->size); @@ -1676,7 +1736,7 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in if (do_render && rndr->cb.blockhtml) rndr->cb.blockhtml(ob, &work, rndr->opaque); return work.size; - } + } } /* HR, which is the only self-closing block tag considered */ @@ -1694,7 +1754,7 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in rndr->cb.blockhtml(ob, &work, rndr->opaque); return work.size; } - } + } } /* no special case recognised */ @@ -1726,7 +1786,7 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in found = 1; break; } - } + } } if (!found) return 0; @@ -1979,7 +2039,7 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size) /* is_ref • returns whether a line is a reference or not */ static int -is_ref(char *data, size_t beg, size_t end, size_t *last, struct array *refs) +is_ref(char *data, size_t beg, size_t end, size_t *last, struct link_ref **refs) { /* int n; */ size_t i = 0; @@ -1987,8 +2047,6 @@ is_ref(char *data, size_t beg, size_t end, size_t *last, struct array *refs) size_t link_offset, link_end; size_t title_offset, title_end; size_t line_end; - struct link_ref *lr; -/* struct buf id = { 0, 0, 0, 0, 0 }; / * volatile buf for id search */ /* up to 3 optional leading spaces */ if (beg + 3 >= end) return 0; @@ -2062,22 +2120,33 @@ is_ref(char *data, size_t beg, size_t end, size_t *last, struct array *refs) && (data[i] == '\'' || data[i] == '"' || data[i] == ')')) { line_end = title_end; title_end = i; } } - if (!line_end) return 0; /* garbage after the link */ + + if (!line_end) + return 0; /* garbage after the link */ /* a valid ref has been found, filling-in return structures */ - if (last) *last = line_end; - if (!refs) return 1; - lr = arr_item(refs, arr_newitem(refs)); - lr->id = bufnew(id_end - id_offset); - bufput(lr->id, data + id_offset, id_end - id_offset); - lr->link = bufnew(link_end - link_offset); - bufput(lr->link, data + link_offset, link_end - link_offset); - if (title_end > title_offset) { - lr->title = bufnew(title_end - title_offset); - bufput(lr->title, data + title_offset, - title_end - title_offset); } - else lr->title = 0; - return 1; + if (last) + *last = line_end; + + if (refs) { + char *title_str = NULL; + size_t title_size = 0; + + if (title_end > title_offset) { + title_str = data + title_offset; + title_size = title_end - title_offset; + } + + add_link_ref( refs, + data + id_offset, /* identifier */ + id_end - id_offset, + data + link_offset, /* link url */ + link_end - link_offset, + title_str, /* title (optional) */ + title_size); + } + + return 1; } static void expand_tabs(struct buf *ob, const char *line, size_t size) @@ -2119,7 +2188,6 @@ sd_markdown(struct buf *ob, static const float MARKDOWN_GROW_FACTOR = 1.4f; - struct link_ref *lr; struct buf *text; size_t i, beg, end; struct render rndr; @@ -2136,12 +2204,10 @@ sd_markdown(struct buf *ob, bufgrow(text, ib->size); memcpy(&rndr.cb, callbacks, sizeof(struct sd_callbacks)); - arr_init(&rndr.refs, sizeof (struct link_ref)); - parr_init(&rndr.work_bufs[BUFFER_BLOCK]); - parr_init(&rndr.work_bufs[BUFFER_SPAN]); + memset(&rndr.refs, 0x0, REF_TABLE_SIZE * sizeof(void *)); -/* for (i = 0; i < 256; i++) - rndr.active_char[i] = 0; */ + stack_init(&rndr.work_bufs[BUFFER_BLOCK], 4); + stack_init(&rndr.work_bufs[BUFFER_SPAN], 8); memset(rndr.active_char, 0x0, 256); @@ -2182,7 +2248,7 @@ sd_markdown(struct buf *ob, /* first pass: looking for references, copying everything else */ beg = 0; while (beg < ib->size) /* iterating over lines */ - if (is_ref(ib->data, beg, ib->size, &end, &rndr.refs)) + if (is_ref(ib->data, beg, ib->size, &end, rndr.refs)) beg = end; else { /* skipping to the next line */ end = beg; @@ -2203,10 +2269,6 @@ sd_markdown(struct buf *ob, beg = end; } - /* sorting the reference array */ - if (rndr.refs.size) - qsort(rndr.refs.base, rndr.refs.size, rndr.refs.unit, cmp_link_ref_sort); - /* pre-grow the output buffer to minimize allocations */ bufgrow(ob, text->size * MARKDOWN_GROW_FACTOR); @@ -2227,14 +2289,7 @@ sd_markdown(struct buf *ob, /* clean-up */ bufrelease(text); - lr = rndr.refs.base; - for (i = 0; i < (size_t)rndr.refs.size; i++) { - bufrelease(lr[i].id); - bufrelease(lr[i].link); - bufrelease(lr[i].title); - } - - arr_free(&rndr.refs); + free_link_refs(rndr.refs); assert(rndr.work_bufs[BUFFER_SPAN].size == 0); assert(rndr.work_bufs[BUFFER_BLOCK].size == 0); @@ -2245,8 +2300,8 @@ sd_markdown(struct buf *ob, for (i = 0; i < (size_t)rndr.work_bufs[BUFFER_BLOCK].asize; ++i) bufrelease(rndr.work_bufs[BUFFER_BLOCK].item[i]); - parr_free(&rndr.work_bufs[BUFFER_SPAN]); - parr_free(&rndr.work_bufs[BUFFER_BLOCK]); + stack_free(&rndr.work_bufs[BUFFER_SPAN]); + stack_free(&rndr.work_bufs[BUFFER_BLOCK]); } void diff --git a/src/markdown.h b/src/markdown.h index 2886cdf..2886cdf 100755..100644 --- a/src/markdown.h +++ b/src/markdown.h |