rinku 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +0 -18
- data/ext/rinku/autolink.c +13 -13
- data/ext/rinku/autolink.h +7 -4
- data/ext/rinku/buffer.c +123 -218
- data/ext/rinku/buffer.h +49 -112
- data/ext/rinku/houdini.h +28 -0
- data/ext/rinku/houdini_href_e.c +108 -0
- data/ext/rinku/houdini_html_e.c +84 -0
- data/ext/rinku/rinku.c +123 -78
- data/lib/rails_rinku.rb +2 -2
- data/rinku.gemspec +4 -1
- data/test/autolink_test.rb +36 -3
- metadata +8 -7
data/Rakefile
CHANGED
@@ -50,21 +50,3 @@ file package('.gem') => %w[pkg/ rinku.gemspec] + $spec.files do |f|
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# GEMSPEC HELPERS ==========================================================
|
53
|
-
|
54
|
-
desc 'Gather required Upskirt sources into extension directory'
|
55
|
-
task :gather => 'upskirt/src/markdown.h' do |t|
|
56
|
-
files =
|
57
|
-
FileList[
|
58
|
-
'upskirt/src/{buffer,autolink}.h',
|
59
|
-
'upskirt/src/{buffer,autolink}.c'
|
60
|
-
]
|
61
|
-
cp files, 'ext/rinku/',
|
62
|
-
:preserve => true,
|
63
|
-
:verbose => true
|
64
|
-
end
|
65
|
-
|
66
|
-
file 'upskirt/src/markdown.h' do |t|
|
67
|
-
abort "The Upskirt submodule is required."
|
68
|
-
end
|
69
|
-
|
70
|
-
|
data/ext/rinku/autolink.c
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
#include <ctype.h>
|
23
23
|
|
24
24
|
int
|
25
|
-
|
25
|
+
sd_autolink_issafe(const uint8_t *link, size_t link_len)
|
26
26
|
{
|
27
27
|
static const size_t valid_uris_count = 4;
|
28
28
|
static const char *valid_uris[] = {
|
@@ -35,7 +35,7 @@ is_safe_link(const char *link, size_t link_len)
|
|
35
35
|
size_t len = strlen(valid_uris[i]);
|
36
36
|
|
37
37
|
if (link_len > len &&
|
38
|
-
strncasecmp(link, valid_uris[i], len) == 0 &&
|
38
|
+
strncasecmp((char *)link, valid_uris[i], len) == 0 &&
|
39
39
|
isalnum(link[len]))
|
40
40
|
return 1;
|
41
41
|
}
|
@@ -44,9 +44,9 @@ is_safe_link(const char *link, size_t link_len)
|
|
44
44
|
}
|
45
45
|
|
46
46
|
static size_t
|
47
|
-
autolink_delim(
|
47
|
+
autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
|
48
48
|
{
|
49
|
-
|
49
|
+
uint8_t cclose, copen = 0;
|
50
50
|
size_t i;
|
51
51
|
|
52
52
|
for (i = 0; i < link_end; ++i)
|
@@ -128,7 +128,7 @@ autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
|
|
128
128
|
}
|
129
129
|
|
130
130
|
static size_t
|
131
|
-
check_domain(
|
131
|
+
check_domain(uint8_t *data, size_t size)
|
132
132
|
{
|
133
133
|
size_t i, np = 0;
|
134
134
|
|
@@ -147,14 +147,14 @@ check_domain(char *data, size_t size)
|
|
147
147
|
}
|
148
148
|
|
149
149
|
size_t
|
150
|
-
|
150
|
+
sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
|
151
151
|
{
|
152
152
|
size_t link_end;
|
153
153
|
|
154
154
|
if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
|
155
155
|
return 0;
|
156
156
|
|
157
|
-
if (size < 4 || memcmp(data, "www.",
|
157
|
+
if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
|
158
158
|
return 0;
|
159
159
|
|
160
160
|
link_end = check_domain(data, size);
|
@@ -177,13 +177,13 @@ ups_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset,
|
|
177
177
|
}
|
178
178
|
|
179
179
|
size_t
|
180
|
-
|
180
|
+
sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
|
181
181
|
{
|
182
182
|
size_t link_end, rewind;
|
183
183
|
int nb = 0, np = 0;
|
184
184
|
|
185
185
|
for (rewind = 0; rewind < offset; ++rewind) {
|
186
|
-
|
186
|
+
uint8_t c = data[-rewind - 1];
|
187
187
|
|
188
188
|
if (isalnum(c))
|
189
189
|
continue;
|
@@ -198,7 +198,7 @@ ups_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offse
|
|
198
198
|
return 0;
|
199
199
|
|
200
200
|
for (link_end = 0; link_end < size; ++link_end) {
|
201
|
-
|
201
|
+
uint8_t c = data[link_end];
|
202
202
|
|
203
203
|
if (isalnum(c))
|
204
204
|
continue;
|
@@ -226,7 +226,7 @@ ups_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offse
|
|
226
226
|
}
|
227
227
|
|
228
228
|
size_t
|
229
|
-
|
229
|
+
sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
|
230
230
|
{
|
231
231
|
size_t link_end, rewind = 0, domain_len;
|
232
232
|
|
@@ -236,9 +236,9 @@ ups_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset,
|
|
236
236
|
while (rewind < offset && isalpha(data[-rewind - 1]))
|
237
237
|
rewind++;
|
238
238
|
|
239
|
-
if (!
|
239
|
+
if (!sd_autolink_issafe(data - rewind, size + rewind))
|
240
240
|
return 0;
|
241
|
-
link_end =
|
241
|
+
link_end = strlen("://");
|
242
242
|
|
243
243
|
domain_len = check_domain(data + link_end, size - link_end);
|
244
244
|
if (domain_len == 0)
|
data/ext/rinku/autolink.h
CHANGED
@@ -15,18 +15,21 @@
|
|
15
15
|
*/
|
16
16
|
|
17
17
|
#ifndef UPSKIRT_AUTOLINK_H
|
18
|
-
#define
|
18
|
+
#define UPSKIRT_AUTOLINK_H
|
19
19
|
|
20
20
|
#include "buffer.h"
|
21
21
|
|
22
|
+
extern int
|
23
|
+
sd_autolink_issafe(const uint8_t *link, size_t link_len);
|
24
|
+
|
22
25
|
extern size_t
|
23
|
-
|
26
|
+
sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
|
24
27
|
|
25
28
|
extern size_t
|
26
|
-
|
29
|
+
sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
|
27
30
|
|
28
31
|
extern size_t
|
29
|
-
|
32
|
+
sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
|
30
33
|
|
31
34
|
#endif
|
32
35
|
|
data/ext/rinku/buffer.c
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
/* buffer.c - automatic buffer structure */
|
2
|
-
|
3
1
|
/*
|
4
2
|
* Copyright (c) 2008, Natacha Porté
|
3
|
+
* Copyright (c) 2011, Vicent Martí
|
5
4
|
*
|
6
5
|
* Permission to use, copy, modify, and distribute this software for any
|
7
6
|
* purpose with or without fee is hereby granted, provided that the above
|
@@ -16,13 +15,6 @@
|
|
16
15
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
17
16
|
*/
|
18
17
|
|
19
|
-
/*
|
20
|
-
* COMPILE TIME OPTIONS
|
21
|
-
*
|
22
|
-
* BUFFER_STATS • if defined, stats are kept about memory usage
|
23
|
-
*/
|
24
|
-
|
25
|
-
#define BUFFER_STDARG
|
26
18
|
#define BUFFER_MAX_ALLOC_SIZE (1024 * 1024 * 16) //16mb
|
27
19
|
|
28
20
|
#include "buffer.h"
|
@@ -31,78 +23,13 @@
|
|
31
23
|
#include <stdlib.h>
|
32
24
|
#include <string.h>
|
33
25
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
#ifdef BUFFER_STATS
|
40
|
-
long buffer_stat_nb = 0;
|
41
|
-
size_t buffer_stat_alloc_bytes = 0;
|
26
|
+
/* MSVC compat */
|
27
|
+
#if defined(_MSC_VER)
|
28
|
+
# define _buf_vsnprintf _vsnprintf
|
29
|
+
#else
|
30
|
+
# define _buf_vsnprintf vsnprintf
|
42
31
|
#endif
|
43
32
|
|
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
33
|
int
|
107
34
|
bufprefix(const struct buf *buf, const char *prefix)
|
108
35
|
{
|
@@ -119,200 +46,179 @@ bufprefix(const struct buf *buf, const char *prefix)
|
|
119
46
|
return 0;
|
120
47
|
}
|
121
48
|
|
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 */
|
49
|
+
/* bufgrow: increasing the allocated size to the given value */
|
152
50
|
int
|
153
|
-
bufgrow(struct buf *buf, size_t neosz)
|
51
|
+
bufgrow(struct buf *buf, size_t neosz)
|
52
|
+
{
|
154
53
|
size_t neoasz;
|
155
54
|
void *neodata;
|
156
|
-
if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE)
|
157
|
-
|
55
|
+
if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE)
|
56
|
+
return BUF_ENOMEM;
|
57
|
+
|
58
|
+
if (buf->asize >= neosz)
|
59
|
+
return BUF_OK;
|
60
|
+
|
158
61
|
neoasz = buf->asize + buf->unit;
|
159
|
-
while (neoasz < neosz)
|
62
|
+
while (neoasz < neosz)
|
63
|
+
neoasz += buf->unit;
|
64
|
+
|
160
65
|
neodata = realloc(buf->data, neoasz);
|
161
|
-
if (!neodata)
|
162
|
-
|
163
|
-
|
164
|
-
#endif
|
66
|
+
if (!neodata)
|
67
|
+
return BUF_ENOMEM;
|
68
|
+
|
165
69
|
buf->data = neodata;
|
166
70
|
buf->asize = neoasz;
|
167
|
-
return
|
71
|
+
return BUF_OK;
|
72
|
+
}
|
168
73
|
|
169
74
|
|
170
|
-
/* bufnew
|
75
|
+
/* bufnew: allocation of a new buffer */
|
171
76
|
struct buf *
|
172
|
-
bufnew(size_t unit)
|
77
|
+
bufnew(size_t unit)
|
78
|
+
{
|
173
79
|
struct buf *ret;
|
174
80
|
ret = malloc(sizeof (struct buf));
|
81
|
+
|
175
82
|
if (ret) {
|
176
|
-
#ifdef BUFFER_STATS
|
177
|
-
buffer_stat_nb += 1;
|
178
|
-
#endif
|
179
83
|
ret->data = 0;
|
180
84
|
ret->size = ret->asize = 0;
|
181
|
-
ret->
|
182
|
-
|
183
|
-
return ret;
|
85
|
+
ret->unit = unit;
|
86
|
+
}
|
87
|
+
return ret;
|
88
|
+
}
|
184
89
|
|
90
|
+
/* bufnullterm: NULL-termination of the string array */
|
91
|
+
const char *
|
92
|
+
bufcstr(struct buf *buf)
|
93
|
+
{
|
94
|
+
if (!buf || !buf->unit)
|
95
|
+
return NULL;
|
185
96
|
|
186
|
-
|
187
|
-
|
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 (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1))
|
192
|
-
buf->data[buf->size] = 0; }
|
97
|
+
if (buf->size < buf->asize && buf->data[buf->size] == 0)
|
98
|
+
return (char *)buf->data;
|
193
99
|
|
100
|
+
if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) {
|
101
|
+
buf->data[buf->size] = 0;
|
102
|
+
return (char *)buf->data;
|
103
|
+
}
|
104
|
+
|
105
|
+
return NULL;
|
106
|
+
}
|
194
107
|
|
195
|
-
/* bufprintf
|
108
|
+
/* bufprintf: formatted printing to a buffer */
|
196
109
|
void
|
197
|
-
bufprintf(struct buf *buf, const char *fmt, ...)
|
110
|
+
bufprintf(struct buf *buf, const char *fmt, ...)
|
111
|
+
{
|
198
112
|
va_list ap;
|
199
|
-
if (!buf || !buf->unit)
|
113
|
+
if (!buf || !buf->unit)
|
114
|
+
return;
|
115
|
+
|
200
116
|
va_start(ap, fmt);
|
201
117
|
vbufprintf(buf, fmt, ap);
|
202
|
-
va_end(ap);
|
203
|
-
|
118
|
+
va_end(ap);
|
119
|
+
}
|
204
120
|
|
205
|
-
/* bufput
|
121
|
+
/* bufput: appends raw data to a buffer */
|
206
122
|
void
|
207
|
-
bufput(struct buf *buf, const void *data, size_t len)
|
208
|
-
|
209
|
-
if (
|
123
|
+
bufput(struct buf *buf, const void *data, size_t len)
|
124
|
+
{
|
125
|
+
if (!buf)
|
210
126
|
return;
|
211
|
-
memcpy(buf->data + buf->size, data, len);
|
212
|
-
buf->size += len; }
|
213
127
|
|
128
|
+
if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
|
129
|
+
return;
|
214
130
|
|
215
|
-
|
131
|
+
memcpy(buf->data + buf->size, data, len);
|
132
|
+
buf->size += len;
|
133
|
+
}
|
134
|
+
|
135
|
+
/* bufputs: appends a NUL-terminated string to a buffer */
|
216
136
|
void
|
217
|
-
bufputs(struct buf *buf, const char *str)
|
218
|
-
|
137
|
+
bufputs(struct buf *buf, const char *str)
|
138
|
+
{
|
139
|
+
bufput(buf, str, strlen(str));
|
140
|
+
}
|
219
141
|
|
220
142
|
|
221
|
-
/* bufputc
|
143
|
+
/* bufputc: appends a single uint8_t to a buffer */
|
222
144
|
void
|
223
|
-
bufputc(struct buf *buf,
|
224
|
-
|
225
|
-
if (
|
145
|
+
bufputc(struct buf *buf, int c)
|
146
|
+
{
|
147
|
+
if (!buf)
|
226
148
|
return;
|
227
|
-
buf->data[buf->size] = c;
|
228
|
-
buf->size += 1; }
|
229
|
-
|
230
149
|
|
231
|
-
|
232
|
-
|
233
|
-
bufrelease(struct buf *buf) {
|
234
|
-
if (!buf) return;
|
235
|
-
buf->ref -= 1;
|
236
|
-
if (buf->ref == 0) {
|
237
|
-
#ifdef BUFFER_STATS
|
238
|
-
buffer_stat_nb -= 1;
|
239
|
-
buffer_stat_alloc_bytes -= buf->asize;
|
240
|
-
#endif
|
241
|
-
free(buf->data);
|
242
|
-
free(buf); } }
|
150
|
+
if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
151
|
+
return;
|
243
152
|
|
153
|
+
buf->data[buf->size] = c;
|
154
|
+
buf->size += 1;
|
155
|
+
}
|
244
156
|
|
245
|
-
/*
|
157
|
+
/* bufrelease: decrease the reference count and free the buffer if needed */
|
246
158
|
void
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
159
|
+
bufrelease(struct buf *buf)
|
160
|
+
{
|
161
|
+
if (!buf)
|
162
|
+
return;
|
163
|
+
|
252
164
|
free(buf->data);
|
253
|
-
buf
|
254
|
-
|
165
|
+
free(buf);
|
166
|
+
}
|
255
167
|
|
256
168
|
|
257
|
-
/*
|
169
|
+
/* bufreset: frees internal data of the buffer */
|
258
170
|
void
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
bufrelease(*dest);
|
264
|
-
*dest = src; }
|
171
|
+
bufreset(struct buf *buf)
|
172
|
+
{
|
173
|
+
if (!buf)
|
174
|
+
return;
|
265
175
|
|
176
|
+
free(buf->data);
|
177
|
+
buf->data = NULL;
|
178
|
+
buf->size = buf->asize = 0;
|
179
|
+
}
|
266
180
|
|
267
|
-
/* bufslurp
|
181
|
+
/* bufslurp: removes a given number of bytes from the head of the array */
|
268
182
|
void
|
269
|
-
bufslurp(struct buf *buf, size_t len)
|
270
|
-
|
183
|
+
bufslurp(struct buf *buf, size_t len)
|
184
|
+
{
|
185
|
+
if (!buf || !buf->unit || len <= 0)
|
186
|
+
return;
|
187
|
+
|
271
188
|
if (len >= buf->size) {
|
272
189
|
buf->size = 0;
|
273
|
-
return;
|
274
|
-
|
275
|
-
memmove(buf->data, buf->data + len, buf->size); }
|
190
|
+
return;
|
191
|
+
}
|
276
192
|
|
193
|
+
buf->size -= len;
|
194
|
+
memmove(buf->data, buf->data + len, buf->size);
|
195
|
+
}
|
277
196
|
|
278
|
-
/*
|
279
|
-
int
|
280
|
-
buftoi(struct buf *buf, size_t offset_i, size_t *offset_o) {
|
281
|
-
int r = 0, neg = 0;
|
282
|
-
size_t i = offset_i;
|
283
|
-
if (!buf || !buf->size) return 0;
|
284
|
-
if (buf->data[i] == '+') i += 1;
|
285
|
-
else if (buf->data[i] == '-') {
|
286
|
-
neg = 1;
|
287
|
-
i += 1; }
|
288
|
-
while (i < buf->size && buf->data[i] >= '0' && buf->data[i] <= '9') {
|
289
|
-
r = (r * 10) + buf->data[i] - '0';
|
290
|
-
i += 1; }
|
291
|
-
if (offset_o) *offset_o = i;
|
292
|
-
return neg ? -r : r; }
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
/* vbufprintf • stdarg variant of formatted printing into a buffer */
|
197
|
+
/* vbufprintf: stdarg variant of formatted printing into a buffer */
|
297
198
|
void
|
298
|
-
vbufprintf(struct buf *buf, const char *fmt, va_list ap)
|
199
|
+
vbufprintf(struct buf *buf, const char *fmt, va_list ap)
|
200
|
+
{
|
299
201
|
int n;
|
300
|
-
|
301
|
-
if (buf == 0
|
302
|
-
|| (buf->size >= buf->asize && !bufgrow (buf, buf->size + 1)))
|
202
|
+
|
203
|
+
if (buf == 0 || (buf->size >= buf->asize && bufgrow(buf, buf->size + 1)) < 0)
|
303
204
|
return;
|
304
205
|
|
305
|
-
|
306
|
-
|
206
|
+
n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
207
|
+
|
208
|
+
if (n < 0) {
|
209
|
+
#ifdef _MSC_VER
|
210
|
+
n = _vscprintf(fmt, ap);
|
211
|
+
#else
|
212
|
+
return;
|
213
|
+
#endif
|
214
|
+
}
|
307
215
|
|
308
|
-
if (
|
309
|
-
|
310
|
-
if (!bufgrow (buf, buf->size + new_size + 1))
|
216
|
+
if ((size_t)n >= buf->asize - buf->size) {
|
217
|
+
if (bufgrow(buf, buf->size + n + 1) < 0)
|
311
218
|
return;
|
312
219
|
|
313
|
-
n =
|
220
|
+
n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
314
221
|
}
|
315
|
-
va_end(ap_save);
|
316
222
|
|
317
223
|
if (n < 0)
|
318
224
|
return;
|
@@ -320,4 +226,3 @@ vbufprintf(struct buf *buf, const char *fmt, va_list ap) {
|
|
320
226
|
buf->size += n;
|
321
227
|
}
|
322
228
|
|
323
|
-
/* vim: set filetype=c: */
|