redcarpet 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of redcarpet might be problematic. Click here for more details.
- data/COPYING +14 -0
- data/README.markdown +38 -0
- data/Rakefile +135 -0
- data/bin/redcarpet +13 -0
- data/ext/array.c +300 -0
- data/ext/array.h +148 -0
- data/ext/buffer.c +318 -0
- data/ext/buffer.h +147 -0
- data/ext/extconf.rb +4 -0
- data/ext/markdown.c +1590 -0
- data/ext/markdown.h +124 -0
- data/ext/redcarpet.c +86 -0
- data/ext/render.c +499 -0
- data/lib/markdown.rb +1 -0
- data/lib/redcarpet.rb +72 -0
- data/redcarpet.gemspec +39 -0
- data/test/benchmark.rb +56 -0
- data/test/benchmark.txt +306 -0
- data/test/markdown_test.rb +176 -0
- data/test/redcarpet_test.rb +106 -0
- metadata +88 -0
data/ext/array.h
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
/* array.h - automatic dynamic array for pointers */
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Copyright (c) 2008, Natacha Porté
|
5
|
+
*
|
6
|
+
* Permission to use, copy, modify, and distribute this software for any
|
7
|
+
* purpose with or without fee is hereby granted, provided that the above
|
8
|
+
* copyright notice and this permission notice appear in all copies.
|
9
|
+
*
|
10
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
11
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
12
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
13
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
14
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
15
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
16
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#ifndef LITHIUM_ARRAY_H
|
20
|
+
#define LITHIUM_ARRAY_H
|
21
|
+
|
22
|
+
#include <stdlib.h>
|
23
|
+
|
24
|
+
|
25
|
+
/********************
|
26
|
+
* TYPE DEFINITIONS *
|
27
|
+
********************/
|
28
|
+
|
29
|
+
/* struct array • generic linear array */
|
30
|
+
struct array {
|
31
|
+
void* base;
|
32
|
+
int size;
|
33
|
+
int asize;
|
34
|
+
size_t unit; };
|
35
|
+
|
36
|
+
|
37
|
+
/* struct parray • array of pointers */
|
38
|
+
struct parray {
|
39
|
+
void ** item;
|
40
|
+
int size;
|
41
|
+
int asize; };
|
42
|
+
|
43
|
+
|
44
|
+
/* array_cmp_fn • comparison functions for sorted arrays */
|
45
|
+
typedef int (*array_cmp_fn)(void *key, void *array_entry);
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
/***************************
|
50
|
+
* GENERIC ARRAY FUNCTIONS *
|
51
|
+
***************************/
|
52
|
+
|
53
|
+
/* arr_adjust • shrink the allocated memory to fit exactly the needs */
|
54
|
+
int
|
55
|
+
arr_adjust(struct array *);
|
56
|
+
|
57
|
+
/* arr_free • frees the structure contents (buf NOT the struct itself) */
|
58
|
+
void
|
59
|
+
arr_free(struct array *);
|
60
|
+
|
61
|
+
/* arr_grow • increases the array size to fit the given number of elements */
|
62
|
+
int
|
63
|
+
arr_grow(struct array *, int);
|
64
|
+
|
65
|
+
/* arr_init • initialization of the contents of the struct */
|
66
|
+
void
|
67
|
+
arr_init(struct array *, size_t);
|
68
|
+
|
69
|
+
/* arr_insert • inserting elements nb before the nth one */
|
70
|
+
int
|
71
|
+
arr_insert(struct array *, int nb, int n);
|
72
|
+
|
73
|
+
/* arr_item • returns a pointer to the n-th element */
|
74
|
+
void *
|
75
|
+
arr_item(struct array *, int);
|
76
|
+
|
77
|
+
/* arr_newitem • returns the index of a new element appended to the array */
|
78
|
+
int
|
79
|
+
arr_newitem(struct array *);
|
80
|
+
|
81
|
+
/* arr_remove • removes the n-th elements of the array */
|
82
|
+
void
|
83
|
+
arr_remove(struct array *, int);
|
84
|
+
|
85
|
+
/* arr_sorted_find • O(log n) search in a sorted array, returning entry */
|
86
|
+
/* equivalent to bsearch(key, arr->base, arr->size, arr->unit, cmp) */
|
87
|
+
void *
|
88
|
+
arr_sorted_find(struct array *, void *key, array_cmp_fn cmp);
|
89
|
+
|
90
|
+
/* arr_sorted_find_i • O(log n) search in a sorted array,
|
91
|
+
* returning index of the smallest element larger than the key */
|
92
|
+
int
|
93
|
+
arr_sorted_find_i(struct array *, void *key, array_cmp_fn cmp);
|
94
|
+
|
95
|
+
|
96
|
+
/***************************
|
97
|
+
* POINTER ARRAY FUNCTIONS *
|
98
|
+
***************************/
|
99
|
+
|
100
|
+
/* parr_adjust • shrinks the allocated memory to fit exactly the needs */
|
101
|
+
int
|
102
|
+
parr_adjust(struct parray *);
|
103
|
+
|
104
|
+
/* parr_free • frees the structure contents (buf NOT the struct itself) */
|
105
|
+
void
|
106
|
+
parr_free(struct parray *);
|
107
|
+
|
108
|
+
/* parr_grow • increases the array size to fit the given number of elements */
|
109
|
+
int
|
110
|
+
parr_grow(struct parray *, int);
|
111
|
+
|
112
|
+
/* parr_init • initialization of the struct (which is equivalent to zero) */
|
113
|
+
void
|
114
|
+
parr_init(struct parray *);
|
115
|
+
|
116
|
+
/* parr_insert • inserting nb elements before the nth one */
|
117
|
+
int
|
118
|
+
parr_insert(struct parray *, int nb, int n);
|
119
|
+
|
120
|
+
/* parr_pop • pops the last item of the array and returns it */
|
121
|
+
void *
|
122
|
+
parr_pop(struct parray *);
|
123
|
+
|
124
|
+
/* parr_push • pushes a pointer at the end of the array (= append) */
|
125
|
+
int
|
126
|
+
parr_push(struct parray *, void *);
|
127
|
+
|
128
|
+
/* parr_remove • removes the n-th element of the array and returns it */
|
129
|
+
void *
|
130
|
+
parr_remove(struct parray *, int);
|
131
|
+
|
132
|
+
/* parr_sorted_find • O(log n) search in a sorted array, returning entry */
|
133
|
+
void *
|
134
|
+
parr_sorted_find(struct parray *, void *key, array_cmp_fn cmp);
|
135
|
+
|
136
|
+
/* parr_sorted_find_i • O(log n) search in a sorted array,
|
137
|
+
* returning index of the smallest element larger than the key */
|
138
|
+
int
|
139
|
+
parr_sorted_find_i(struct parray *, void *key, array_cmp_fn cmp);
|
140
|
+
|
141
|
+
/* parr_top • returns the top the stack (i.e. the last element of the array) */
|
142
|
+
void *
|
143
|
+
parr_top(struct parray *);
|
144
|
+
|
145
|
+
|
146
|
+
#endif /* ndef LITHIUM_ARRAY_H */
|
147
|
+
|
148
|
+
/* vim: set filetype=c: */
|
data/ext/buffer.c
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
/* buffer.c - automatic buffer structure */
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Copyright (c) 2008, Natacha Porté
|
5
|
+
*
|
6
|
+
* Permission to use, copy, modify, and distribute this software for any
|
7
|
+
* purpose with or without fee is hereby granted, provided that the above
|
8
|
+
* copyright notice and this permission notice appear in all copies.
|
9
|
+
*
|
10
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
11
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
12
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
13
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
14
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
15
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
16
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
17
|
+
*/
|
18
|
+
|
19
|
+
/*
|
20
|
+
* COMPILE TIME OPTIONS
|
21
|
+
*
|
22
|
+
* BUFFER_STATS • if defined, stats are kept about memory usage
|
23
|
+
*/
|
24
|
+
#define BUFFER_STATS
|
25
|
+
|
26
|
+
#define BUFFER_STDARG
|
27
|
+
|
28
|
+
#include "buffer.h"
|
29
|
+
|
30
|
+
#include <stdio.h>
|
31
|
+
#include <stdlib.h>
|
32
|
+
#include <string.h>
|
33
|
+
|
34
|
+
|
35
|
+
/********************
|
36
|
+
* GLOBAL VARIABLES *
|
37
|
+
********************/
|
38
|
+
|
39
|
+
#ifdef BUFFER_STATS
|
40
|
+
long buffer_stat_nb = 0;
|
41
|
+
size_t buffer_stat_alloc_bytes = 0;
|
42
|
+
#endif
|
43
|
+
|
44
|
+
|
45
|
+
/***************************
|
46
|
+
* STATIC HELPER FUNCTIONS *
|
47
|
+
***************************/
|
48
|
+
|
49
|
+
/* lower • retruns the lower-case variant of the input char */
|
50
|
+
static char
|
51
|
+
lower(char c) {
|
52
|
+
return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; }
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
/********************
|
57
|
+
* BUFFER FUNCTIONS *
|
58
|
+
********************/
|
59
|
+
|
60
|
+
/* bufcasecmp • case-insensitive buffer comparison */
|
61
|
+
int
|
62
|
+
bufcasecmp(const struct buf *a, const struct buf *b) {
|
63
|
+
size_t i = 0;
|
64
|
+
size_t cmplen;
|
65
|
+
if (a == b) return 0;
|
66
|
+
if (!a) return -1; else if (!b) return 1;
|
67
|
+
cmplen = (a->size < b->size) ? a->size : b->size;
|
68
|
+
while (i < cmplen && lower(a->data[i]) == lower(b->data[i])) ++i;
|
69
|
+
if (i < a->size) {
|
70
|
+
if (i < b->size) return lower(a->data[i]) - lower(b->data[i]);
|
71
|
+
else return 1; }
|
72
|
+
else { if (i < b->size) return -1;
|
73
|
+
else return 0; } }
|
74
|
+
|
75
|
+
|
76
|
+
/* bufcmp • case-sensitive buffer comparison */
|
77
|
+
int
|
78
|
+
bufcmp(const struct buf *a, const struct buf *b) {
|
79
|
+
size_t i = 0;
|
80
|
+
size_t cmplen;
|
81
|
+
if (a == b) return 0;
|
82
|
+
if (!a) return -1; else if (!b) return 1;
|
83
|
+
cmplen = (a->size < b->size) ? a->size : b->size;
|
84
|
+
while (i < cmplen && a->data[i] == b->data[i]) ++i;
|
85
|
+
if (i < a->size) {
|
86
|
+
if (i < b->size) return a->data[i] - b->data[i];
|
87
|
+
else return 1; }
|
88
|
+
else { if (i < b->size) return -1;
|
89
|
+
else return 0; } }
|
90
|
+
|
91
|
+
|
92
|
+
/* bufcmps • case-sensitive comparison of a string to a buffer */
|
93
|
+
int
|
94
|
+
bufcmps(const struct buf *a, const char *b) {
|
95
|
+
const size_t len = strlen(b);
|
96
|
+
size_t cmplen = len;
|
97
|
+
int r;
|
98
|
+
if (!a || !a->size) return b ? 0 : -1;
|
99
|
+
if (len < a->size) cmplen = a->size;
|
100
|
+
r = strncmp(a->data, b, cmplen);
|
101
|
+
if (r) return r;
|
102
|
+
else if (a->size == len) return 0;
|
103
|
+
else if (a->size < len) return -1;
|
104
|
+
else return 1; }
|
105
|
+
|
106
|
+
int
|
107
|
+
bufprefix(const struct buf *buf, const char *prefix)
|
108
|
+
{
|
109
|
+
size_t i;
|
110
|
+
|
111
|
+
for (i = 0; i < buf->size; ++i) {
|
112
|
+
if (prefix[i] == 0)
|
113
|
+
return 0;
|
114
|
+
|
115
|
+
if (buf->data[i] != prefix[i])
|
116
|
+
return buf->data[i] - prefix[i];
|
117
|
+
}
|
118
|
+
|
119
|
+
return 0;
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
/* bufdup • buffer duplication */
|
124
|
+
struct buf *
|
125
|
+
bufdup(const struct buf *src, size_t dupunit) {
|
126
|
+
size_t blocks;
|
127
|
+
struct buf *ret;
|
128
|
+
if (src == 0) return 0;
|
129
|
+
ret = malloc(sizeof (struct buf));
|
130
|
+
if (ret == 0) return 0;
|
131
|
+
ret->unit = dupunit;
|
132
|
+
ret->size = src->size;
|
133
|
+
ret->ref = 1;
|
134
|
+
if (!src->size) {
|
135
|
+
ret->asize = 0;
|
136
|
+
ret->data = 0;
|
137
|
+
return ret; }
|
138
|
+
blocks = (src->size + dupunit - 1) / dupunit;
|
139
|
+
ret->asize = blocks * dupunit;
|
140
|
+
ret->data = malloc(ret->asize);
|
141
|
+
if (ret->data == 0) {
|
142
|
+
free(ret);
|
143
|
+
return 0; }
|
144
|
+
memcpy(ret->data, src->data, src->size);
|
145
|
+
#ifdef BUFFER_STATS
|
146
|
+
buffer_stat_nb += 1;
|
147
|
+
buffer_stat_alloc_bytes += ret->asize;
|
148
|
+
#endif
|
149
|
+
return ret; }
|
150
|
+
|
151
|
+
/* bufgrow • increasing the allocated size to the given value */
|
152
|
+
int
|
153
|
+
bufgrow(struct buf *buf, size_t neosz) {
|
154
|
+
size_t neoasz;
|
155
|
+
void *neodata;
|
156
|
+
if (!buf || !buf->unit) return 0;
|
157
|
+
if (buf->asize >= neosz) return 1;
|
158
|
+
neoasz = buf->asize + buf->unit;
|
159
|
+
while (neoasz < neosz) neoasz += buf->unit;
|
160
|
+
neodata = realloc(buf->data, neoasz);
|
161
|
+
if (!neodata) return 0;
|
162
|
+
#ifdef BUFFER_STATS
|
163
|
+
buffer_stat_alloc_bytes += (neoasz - buf->asize);
|
164
|
+
#endif
|
165
|
+
buf->data = neodata;
|
166
|
+
buf->asize = neoasz;
|
167
|
+
return 1; }
|
168
|
+
|
169
|
+
|
170
|
+
/* bufnew • allocation of a new buffer */
|
171
|
+
struct buf *
|
172
|
+
bufnew(size_t unit) {
|
173
|
+
struct buf *ret;
|
174
|
+
ret = malloc(sizeof (struct buf));
|
175
|
+
if (ret) {
|
176
|
+
#ifdef BUFFER_STATS
|
177
|
+
buffer_stat_nb += 1;
|
178
|
+
#endif
|
179
|
+
ret->data = 0;
|
180
|
+
ret->size = ret->asize = 0;
|
181
|
+
ret->ref = 1;
|
182
|
+
ret->unit = unit; }
|
183
|
+
return ret; }
|
184
|
+
|
185
|
+
|
186
|
+
/* bufnullterm • NUL-termination of the string array (making a C-string) */
|
187
|
+
void
|
188
|
+
bufnullterm(struct buf *buf) {
|
189
|
+
if (!buf || !buf->unit) return;
|
190
|
+
if (buf->size < buf->asize && buf->data[buf->size] == 0) return;
|
191
|
+
if (bufgrow(buf, buf->size + 1))
|
192
|
+
buf->data[buf->size] = 0; }
|
193
|
+
|
194
|
+
|
195
|
+
/* bufprintf • formatted printing to a buffer */
|
196
|
+
void
|
197
|
+
bufprintf(struct buf *buf, const char *fmt, ...) {
|
198
|
+
va_list ap;
|
199
|
+
if (!buf || !buf->unit) return;
|
200
|
+
va_start(ap, fmt);
|
201
|
+
vbufprintf(buf, fmt, ap);
|
202
|
+
va_end(ap); }
|
203
|
+
|
204
|
+
|
205
|
+
/* bufput • appends raw data to a buffer */
|
206
|
+
void
|
207
|
+
bufput(struct buf *buf, const void *data, size_t len) {
|
208
|
+
if (!buf || !bufgrow(buf, buf->size + len)) return;
|
209
|
+
memcpy(buf->data + buf->size, data, len);
|
210
|
+
buf->size += len; }
|
211
|
+
|
212
|
+
|
213
|
+
/* bufputs • appends a NUL-terminated string to a buffer */
|
214
|
+
void
|
215
|
+
bufputs(struct buf *buf, const char *str) {
|
216
|
+
bufput(buf, str, strlen (str)); }
|
217
|
+
|
218
|
+
|
219
|
+
/* bufputc • appends a single char to a buffer */
|
220
|
+
void
|
221
|
+
bufputc(struct buf *buf, char c) {
|
222
|
+
if (!buf || !bufgrow(buf, buf->size + 1)) return;
|
223
|
+
buf->data[buf->size] = c;
|
224
|
+
buf->size += 1; }
|
225
|
+
|
226
|
+
|
227
|
+
/* bufrelease • decrease the reference count and free the buffer if needed */
|
228
|
+
void
|
229
|
+
bufrelease(struct buf *buf) {
|
230
|
+
if (!buf || !buf->unit || !buf->asize) return;
|
231
|
+
buf->ref -= 1;
|
232
|
+
if (buf->ref == 0) {
|
233
|
+
#ifdef BUFFER_STATS
|
234
|
+
buffer_stat_nb -= 1;
|
235
|
+
buffer_stat_alloc_bytes -= buf->asize;
|
236
|
+
#endif
|
237
|
+
free(buf->data);
|
238
|
+
free(buf); } }
|
239
|
+
|
240
|
+
|
241
|
+
/* bufreset • frees internal data of the buffer */
|
242
|
+
void
|
243
|
+
bufreset(struct buf *buf) {
|
244
|
+
if (!buf || !buf->unit || !buf->asize) return;
|
245
|
+
#ifdef BUFFER_STATS
|
246
|
+
buffer_stat_alloc_bytes -= buf->asize;
|
247
|
+
#endif
|
248
|
+
free(buf->data);
|
249
|
+
buf->data = 0;
|
250
|
+
buf->size = buf->asize = 0; }
|
251
|
+
|
252
|
+
|
253
|
+
/* bufset • safely assigns a buffer to another */
|
254
|
+
void
|
255
|
+
bufset(struct buf **dest, struct buf *src) {
|
256
|
+
if (src) {
|
257
|
+
if (!src->asize) src = bufdup(src, 1);
|
258
|
+
else src->ref += 1; }
|
259
|
+
bufrelease(*dest);
|
260
|
+
*dest = src; }
|
261
|
+
|
262
|
+
|
263
|
+
/* bufslurp • removes a given number of bytes from the head of the array */
|
264
|
+
void
|
265
|
+
bufslurp(struct buf *buf, size_t len) {
|
266
|
+
if (!buf || !buf->unit || len <= 0) return;
|
267
|
+
if (len >= buf->size) {
|
268
|
+
buf->size = 0;
|
269
|
+
return; }
|
270
|
+
buf->size -= len;
|
271
|
+
memmove(buf->data, buf->data + len, buf->size); }
|
272
|
+
|
273
|
+
|
274
|
+
/* buftoi • converts the numbers at the beginning of the buf into an int */
|
275
|
+
int
|
276
|
+
buftoi(struct buf *buf, size_t offset_i, size_t *offset_o) {
|
277
|
+
int r = 0, neg = 0;
|
278
|
+
size_t i = offset_i;
|
279
|
+
if (!buf || !buf->size) return 0;
|
280
|
+
if (buf->data[i] == '+') i += 1;
|
281
|
+
else if (buf->data[i] == '-') {
|
282
|
+
neg = 1;
|
283
|
+
i += 1; }
|
284
|
+
while (i < buf->size && buf->data[i] >= '0' && buf->data[i] <= '9') {
|
285
|
+
r = (r * 10) + buf->data[i] - '0';
|
286
|
+
i += 1; }
|
287
|
+
if (offset_o) *offset_o = i;
|
288
|
+
return neg ? -r : r; }
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
/* vbufprintf • stdarg variant of formatted printing into a buffer */
|
293
|
+
void
|
294
|
+
vbufprintf(struct buf *buf, const char *fmt, va_list ap) {
|
295
|
+
int n;
|
296
|
+
va_list ap_save;
|
297
|
+
if (buf == 0
|
298
|
+
|| (buf->size >= buf->asize && !bufgrow (buf, buf->size + 1)))
|
299
|
+
return;
|
300
|
+
|
301
|
+
va_copy(ap_save, ap);
|
302
|
+
n = vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
303
|
+
|
304
|
+
if (n < 0 || (size_t)n >= buf->asize - buf->size) {
|
305
|
+
if (!bufgrow (buf, buf->size + n + 1))
|
306
|
+
return;
|
307
|
+
|
308
|
+
n = vsnprintf (buf->data + buf->size, buf->asize - buf->size, fmt, ap_save);
|
309
|
+
}
|
310
|
+
va_end(ap_save);
|
311
|
+
|
312
|
+
if (n < 0)
|
313
|
+
return;
|
314
|
+
|
315
|
+
buf->size += n;
|
316
|
+
}
|
317
|
+
|
318
|
+
/* vim: set filetype=c: */
|