1 |
/* Creation date: 2005-06-26 19:59:10
|
2 |
* Authors: Don
|
3 |
* Change log:
|
4 |
*/
|
5 |
|
6 |
/* Copyright (c) 2005 Don Owens
|
7 |
All rights reserved.
|
8 |
|
9 |
This code is released under the BSD license:
|
10 |
|
11 |
Redistribution and use in source and binary forms, with or without
|
12 |
modification, are permitted provided that the following conditions
|
13 |
are met:
|
14 |
|
15 |
* Redistributions of source code must retain the above copyright
|
16 |
notice, this list of conditions and the following disclaimer.
|
17 |
|
18 |
* Redistributions in binary form must reproduce the above
|
19 |
copyright notice, this list of conditions and the following
|
20 |
disclaimer in the documentation and/or other materials provided
|
21 |
with the distribution.
|
22 |
|
23 |
* Neither the name of the author nor the names of its
|
24 |
contributors may be used to endorse or promote products derived
|
25 |
from this software without specific prior written permission.
|
26 |
|
27 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
28 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
29 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
30 |
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
31 |
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
32 |
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
33 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
34 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
35 |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36 |
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
37 |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
38 |
OF THE POSSIBILITY OF SUCH DAMAGE.
|
39 |
*/
|
40 |
|
41 |
#include "cfu.h"
|
42 |
|
43 |
#include "cfustring.h"
|
44 |
|
45 |
#include <stdlib.h>
|
46 |
#include <stdarg.h>
|
47 |
#include <stdio.h>
|
48 |
|
49 |
#ifdef CFU_DEBUG
|
50 |
#ifdef NDEBUG
|
51 |
#undef NDEBUG
|
52 |
#endif
|
53 |
#else
|
54 |
#ifndef NDEBUG
|
55 |
#define NDEBUG 1
|
56 |
#endif
|
57 |
#endif
|
58 |
#include <assert.h>
|
59 |
|
60 |
struct cfustring {
|
61 |
libcfu_type type;
|
62 |
size_t max_size;
|
63 |
size_t used_size;
|
64 |
char *str;
|
65 |
};
|
66 |
|
67 |
extern cfustring_t *
|
68 |
cfustring_new() {
|
69 |
return cfustring_new_with_initial_size(0);
|
70 |
}
|
71 |
|
72 |
extern cfustring_t *
|
73 |
cfustring_new_with_initial_size(size_t initial_size) {
|
74 |
cfustring_t *cfu_str = (cfustring_t *)calloc(1, sizeof(cfustring_t));
|
75 |
cfu_str->type = libcfu_t_string;
|
76 |
if (initial_size > 0) {
|
77 |
cfu_str->str = (char *)calloc(initial_size, 1);
|
78 |
cfu_str->max_size = initial_size;
|
79 |
cfu_str->used_size = 1;
|
80 |
}
|
81 |
return cfu_str;
|
82 |
}
|
83 |
|
84 |
extern cfustring_t *
|
85 |
cfustring_new_from_string(const char *string) {
|
86 |
cfustring_t *cfu_str = cfustring_new();
|
87 |
cfustring_append(cfu_str, string);
|
88 |
return cfu_str;
|
89 |
}
|
90 |
|
91 |
extern int
|
92 |
cfustring_dup(cfustring_t *cfu_str, const char *string) {
|
93 |
if (!string) {
|
94 |
cfu_str->max_size = 0;
|
95 |
cfu_str->used_size = 0;
|
96 |
free(cfu_str->str);
|
97 |
cfu_str->str = NULL;
|
98 |
return 1;
|
99 |
}
|
100 |
|
101 |
cfustring_clear(cfu_str);
|
102 |
cfustring_append(cfu_str, string);
|
103 |
return 1;
|
104 |
}
|
105 |
|
106 |
extern int
|
107 |
cfustring_clear(cfustring_t *cfu_str) {
|
108 |
if (cfu_str->str) {
|
109 |
cfu_str->str[0] = '\000';
|
110 |
cfu_str->used_size = 1;
|
111 |
}
|
112 |
return 1;
|
113 |
}
|
114 |
|
115 |
extern int
|
116 |
cfustring_append_n(cfustring_t *cfu_str, const char *string, size_t n) {
|
117 |
size_t str_len = 0;
|
118 |
if (!string) return 1;
|
119 |
|
120 |
if (n) {
|
121 |
size_t i = 0;
|
122 |
const char *ptr = string;
|
123 |
for (i = 0; i < n; i++) {
|
124 |
if (*ptr) {
|
125 |
str_len++;
|
126 |
} else {
|
127 |
break;
|
128 |
}
|
129 |
}
|
130 |
} else {
|
131 |
str_len = strlen(string);
|
132 |
}
|
133 |
|
134 |
if (!cfu_str->str) {
|
135 |
cfu_str->str = (char *)malloc(str_len + 1);
|
136 |
cfu_str->max_size = str_len + 1;
|
137 |
cfu_str->used_size = 1;
|
138 |
cfu_str->str[0] = '\000';
|
139 |
}
|
140 |
|
141 |
if (cfu_str->used_size + str_len + 1 > cfu_str->max_size) {
|
142 |
/* allocate more memory and copy over */
|
143 |
char *tmp = NULL;
|
144 |
|
145 |
if (cfu_str->max_size * 2 >= cfu_str->used_size + str_len + 1) {
|
146 |
cfu_str->max_size *= 2;
|
147 |
} else {
|
148 |
cfu_str->max_size = cfu_str->used_size + str_len + 1;
|
149 |
}
|
150 |
tmp = (char *)malloc(cfu_str->max_size);
|
151 |
memcpy(tmp, cfu_str->str, cfu_str->used_size);
|
152 |
free(cfu_str->str);
|
153 |
cfu_str->str = tmp;
|
154 |
}
|
155 |
|
156 |
memcpy(&cfu_str->str[cfu_str->used_size - 1], string, str_len);
|
157 |
/* strcat(cfu_str->str, string); */
|
158 |
cfu_str->used_size += str_len;
|
159 |
cfu_str->str[cfu_str->used_size - 1] = '\000';
|
160 |
|
161 |
|
162 |
return 1;
|
163 |
}
|
164 |
|
165 |
extern int
|
166 |
cfustring_append(cfustring_t *cfu_str, const char *string) {
|
167 |
return cfustring_append_n(cfu_str, string, 0);
|
168 |
}
|
169 |
|
170 |
extern char *
|
171 |
cfustring_get_buffer(cfustring_t *cfu_str) {
|
172 |
return cfu_str->str;
|
173 |
}
|
174 |
|
175 |
extern char *
|
176 |
cfustring_get_buffer_copy(cfustring_t *cfu_str) {
|
177 |
char *buffer = NULL;
|
178 |
if (!cfu_str->str) return NULL;
|
179 |
|
180 |
buffer = (char *)calloc(cfu_str->used_size, 1);
|
181 |
memcpy(buffer, cfu_str->str, cfu_str->used_size);
|
182 |
return buffer;
|
183 |
}
|
184 |
|
185 |
static char *
|
186 |
_dup_str(const char *str) {
|
187 |
size_t len = strlen(str) + 1;
|
188 |
char *ns = (char *)calloc(len, 1);
|
189 |
memcpy(ns, str, len);
|
190 |
return ns;
|
191 |
}
|
192 |
|
193 |
static char *
|
194 |
_dup_str_n(const char *str, size_t n) {
|
195 |
size_t len = n;
|
196 |
char *ns;
|
197 |
|
198 |
if (n == 0) return NULL;
|
199 |
|
200 |
ns = (char *)calloc(len + 1, 1);
|
201 |
memcpy(ns, str, len);
|
202 |
ns[len] = '\000';
|
203 |
return ns;
|
204 |
}
|
205 |
|
206 |
extern char *
|
207 |
cfustring_dup_c_str(const char *str) {
|
208 |
return _dup_str(str);
|
209 |
}
|
210 |
|
211 |
extern char *
|
212 |
cfustring_dup_c_str_n(const char *str, size_t n) {
|
213 |
return _dup_str_n(str, n);
|
214 |
}
|
215 |
|
216 |
static char *
|
217 |
_check_sep(char **start, char **seps, size_t num_seps, char **sep_chk_ptrs, int last) {
|
218 |
size_t i;
|
219 |
char *end = *start;
|
220 |
|
221 |
for (i = 0; i < num_seps; i++) sep_chk_ptrs[i] = seps[i];
|
222 |
|
223 |
if (!*start || !*(*start)) return NULL;
|
224 |
|
225 |
if (last) {
|
226 |
for(; *end; end++);
|
227 |
if (end != *start) {
|
228 |
char *rv = _dup_str_n(*start, end - *start);
|
229 |
*start = end;
|
230 |
return rv;
|
231 |
}
|
232 |
return NULL;
|
233 |
}
|
234 |
|
235 |
for (end = *start; *end; end++) {
|
236 |
for (i = 0; i < num_seps; i++) {
|
237 |
if (*sep_chk_ptrs[i] == *end) {
|
238 |
sep_chk_ptrs[i]++;
|
239 |
if (!*sep_chk_ptrs[i]) {
|
240 |
/* got a match */
|
241 |
size_t size = end - *start + 1 - (sep_chk_ptrs[i] - seps[i]);
|
242 |
char *rv = _dup_str_n(*start, size);
|
243 |
*start = end + 1;
|
244 |
return rv;
|
245 |
}
|
246 |
} else {
|
247 |
sep_chk_ptrs[i] = seps[i];
|
248 |
}
|
249 |
}
|
250 |
}
|
251 |
|
252 |
if (end != *start) {
|
253 |
char *rv = _dup_str_n(*start, end - *start);
|
254 |
*start = end;
|
255 |
return rv;
|
256 |
}
|
257 |
|
258 |
return NULL;
|
259 |
}
|
260 |
|
261 |
static char **
|
262 |
__cfustring_split_to_raw(cfustring_t *cfu_str, size_t *num_strings, size_t num_seps, size_t limit,
|
263 |
va_list ap) {
|
264 |
char *sep = NULL;
|
265 |
size_t i = 0;
|
266 |
char **sep_array = (char **)calloc(num_seps, sizeof(char *));
|
267 |
char **sep_chk_ptrs = (char **)calloc(num_seps, sizeof(char *));
|
268 |
char **ret_strings = (char **)calloc(2, sizeof(char *));
|
269 |
u_int max_ret_strings = 2;
|
270 |
u_int used_ret_strings = 0;
|
271 |
char *start = NULL;
|
272 |
char *end = NULL;
|
273 |
char *next_str = NULL;
|
274 |
int last = 0;
|
275 |
|
276 |
*num_strings = 0;
|
277 |
|
278 |
if (limit == 1) {
|
279 |
ret_strings[0] = cfustring_get_buffer_copy(cfu_str);
|
280 |
*num_strings = 1;
|
281 |
return ret_strings;
|
282 |
}
|
283 |
|
284 |
for (i = 0; i < num_seps; i++) {
|
285 |
sep = va_arg(ap, char *);
|
286 |
sep_array[i] = _dup_str(sep);
|
287 |
}
|
288 |
|
289 |
start = end = cfustring_get_buffer(cfu_str);
|
290 |
if (!end) {
|
291 |
*num_strings = 0;
|
292 |
free(ret_strings);
|
293 |
for (i = 0; i < num_seps; i++) {
|
294 |
free(sep_array[i]);
|
295 |
}
|
296 |
free(sep_array);
|
297 |
return NULL;
|
298 |
}
|
299 |
|
300 |
while ( (next_str = _check_sep(&end, sep_array, num_seps, sep_chk_ptrs, last)) ) {
|
301 |
if (used_ret_strings == max_ret_strings) {
|
302 |
/* allocate more space */
|
303 |
size_t new_size = max_ret_strings << 1;
|
304 |
char **tmp = (char **)calloc(new_size, sizeof(char *));
|
305 |
for (i = 0; i < used_ret_strings; i++) tmp[i] = ret_strings[i];
|
306 |
free(ret_strings);
|
307 |
ret_strings = tmp;
|
308 |
max_ret_strings = new_size;
|
309 |
}
|
310 |
ret_strings[used_ret_strings] = next_str;
|
311 |
used_ret_strings++;
|
312 |
|
313 |
if (limit > 0 && used_ret_strings == limit - 1) {
|
314 |
last = 1;
|
315 |
}
|
316 |
}
|
317 |
|
318 |
for (i = 0; i < num_seps; i++) {
|
319 |
free(sep_array[i]);
|
320 |
}
|
321 |
free(sep_array);
|
322 |
free(sep_chk_ptrs);
|
323 |
|
324 |
*num_strings = used_ret_strings;
|
325 |
return ret_strings;
|
326 |
}
|
327 |
|
328 |
extern cfustring_t **
|
329 |
cfustring_split(cfustring_t *cfu_str, size_t *num_strings, size_t limit, ...) {
|
330 |
va_list ap;
|
331 |
char **strings = NULL;
|
332 |
char *sep = NULL;
|
333 |
cfustring_t **rv = NULL;
|
334 |
size_t i = 0;
|
335 |
size_t num_seps = 0;
|
336 |
|
337 |
va_start(ap, limit);
|
338 |
sep = va_arg(ap, char *);
|
339 |
while (sep) {
|
340 |
num_seps++;
|
341 |
sep = va_arg(ap, char *);
|
342 |
}
|
343 |
va_end(ap);
|
344 |
|
345 |
va_start(ap, limit);
|
346 |
strings = __cfustring_split_to_raw(cfu_str, num_strings, num_seps, limit, ap);
|
347 |
va_end(ap);
|
348 |
|
349 |
if (!*num_strings) return NULL;
|
350 |
rv = (cfustring_t **)malloc(*num_strings * sizeof(cfustring_t *));
|
351 |
for (i = 0; i < *num_strings; i++) {
|
352 |
rv[i] = cfustring_new_from_string(strings[i]);
|
353 |
free(strings[i]);
|
354 |
}
|
355 |
free(strings);
|
356 |
|
357 |
return rv;
|
358 |
}
|
359 |
|
360 |
|
361 |
extern char **
|
362 |
cfustring_split_to_c_str(cfustring_t *cfu_str, size_t *num_strings, size_t limit, ...) {
|
363 |
char **rv = NULL;
|
364 |
va_list ap;
|
365 |
size_t num_seps = 0;
|
366 |
char *sep = NULL;
|
367 |
|
368 |
va_start(ap, limit);
|
369 |
sep = va_arg(ap, char *);
|
370 |
while (sep) {
|
371 |
num_seps++;
|
372 |
sep = va_arg(ap, char *);
|
373 |
}
|
374 |
va_end(ap);
|
375 |
|
376 |
va_start(ap, limit);
|
377 |
rv = __cfustring_split_to_raw(cfu_str, num_strings, num_seps, limit, ap);
|
378 |
va_end(ap);
|
379 |
|
380 |
return rv;
|
381 |
}
|
382 |
|
383 |
extern char *
|
384 |
cfustring_sprintf_c_str(const char *fmt, ...) {
|
385 |
va_list ap;
|
386 |
char *str = NULL;
|
387 |
cfustring_t *cfu_str = cfustring_new();
|
388 |
va_start(ap, fmt);
|
389 |
cfustring_vsprintf(cfu_str, fmt, ap);
|
390 |
va_end(ap);
|
391 |
|
392 |
str = cfustring_get_buffer_copy(cfu_str);
|
393 |
cfustring_destroy(cfu_str);
|
394 |
|
395 |
return str;
|
396 |
}
|
397 |
|
398 |
extern size_t
|
399 |
cfustring_sprintf(cfustring_t *cfu_str, const char *fmt, ...) {
|
400 |
va_list ap;
|
401 |
size_t rv = 0;
|
402 |
va_start(ap, fmt);
|
403 |
rv = cfustring_vsprintf(cfu_str, fmt, ap);
|
404 |
va_end(ap);
|
405 |
|
406 |
return rv;
|
407 |
}
|
408 |
|
409 |
static int
|
410 |
_safe_sprintf(char **buf, size_t *buf_size, const char *fmt, ...) {
|
411 |
va_list ap;
|
412 |
int rv = 0;
|
413 |
int done = 0;
|
414 |
|
415 |
if (!(*buf) || *buf_size == 0) {
|
416 |
*buf_size = 128;
|
417 |
if (*buf) free(*buf);
|
418 |
*buf = (char *)malloc(*buf_size);
|
419 |
}
|
420 |
|
421 |
while (!done) {
|
422 |
va_start(ap, fmt);
|
423 |
rv = vsnprintf(*buf, *buf_size, fmt, ap);
|
424 |
va_end(ap);
|
425 |
if (rv >= (int)(*buf_size) - 1) {
|
426 |
*buf_size *= 2;
|
427 |
free(*buf);
|
428 |
*buf = (char *)malloc(*buf_size);
|
429 |
}
|
430 |
else {
|
431 |
done = 1;
|
432 |
}
|
433 |
}
|
434 |
|
435 |
return rv;
|
436 |
}
|
437 |
|
438 |
static char *
|
439 |
_safe_strncpy(char **buf, size_t *buf_size, const char *src, size_t size) {
|
440 |
char *rv = NULL;
|
441 |
|
442 |
if (!(*buf) || *buf_size == 0) {
|
443 |
*buf_size = size + 1;
|
444 |
if (*buf) free(*buf);
|
445 |
*buf = (char *)malloc(*buf_size);
|
446 |
(*buf)[0] = '\000';
|
447 |
}
|
448 |
|
449 |
if (size > *buf_size - 1) {
|
450 |
*buf_size = size + 1;
|
451 |
if (*buf) free(*buf);
|
452 |
*buf = (char *)malloc(*buf_size);
|
453 |
(*buf)[0] = '\000';
|
454 |
}
|
455 |
|
456 |
rv = strncpy(*buf, src, size);
|
457 |
|
458 |
return rv;
|
459 |
}
|
460 |
|
461 |
extern size_t
|
462 |
cfustring_vsprintf(cfustring_t *cfu_str, const char *fmt_in, va_list ap) {
|
463 |
const char *ptr = NULL;
|
464 |
const char *start = NULL;
|
465 |
const char *end = NULL;
|
466 |
size_t byte_count = 0;
|
467 |
size_t buf_size = 128;
|
468 |
size_t buf2_size = 128;
|
469 |
char *buf = NULL;
|
470 |
char *buf2 = NULL;
|
471 |
const char *fmt = NULL;
|
472 |
|
473 |
buf = (char *)malloc(buf_size);
|
474 |
buf2 = (char *)malloc(buf2_size);
|
475 |
|
476 |
cfustring_clear(cfu_str);
|
477 |
|
478 |
ptr = start = end = fmt = fmt_in;
|
479 |
while (*fmt) {
|
480 |
if (*fmt == '%') {
|
481 |
ptr = fmt;
|
482 |
fmt++;
|
483 |
if (*fmt == '%') {
|
484 |
end++;
|
485 |
cfustring_append_n(cfu_str, start, ptr - start + 1);
|
486 |
byte_count += ptr - start + 1;
|
487 |
|
488 |
fmt++;
|
489 |
start = end = fmt;
|
490 |
continue;
|
491 |
}
|
492 |
|
493 |
while (*fmt && *fmt != 'u' && *fmt != 's' && *fmt != 'd' && *fmt != 'f' && *fmt != 'F'
|
494 |
&& *fmt != 'x' && *fmt != 'X' && *fmt != 'p'
|
495 |
&& *fmt != ' ' && *fmt != '\t') fmt++;
|
496 |
|
497 |
if (*fmt == 'u' || *fmt == 'd' || *fmt == 'f' || *fmt == 'F'
|
498 |
|| *fmt == 'x' || *fmt == 'X' || *fmt == 'p') {
|
499 |
unsigned num = 0;
|
500 |
double f = 0;
|
501 |
int d = 0;
|
502 |
void *p = NULL;
|
503 |
size_t size = fmt - ptr + 1;
|
504 |
|
505 |
_safe_strncpy(&buf2, &buf2_size, ptr, size);
|
506 |
buf2[size] = '\000';
|
507 |
|
508 |
switch (*fmt) {
|
509 |
case 'u':
|
510 |
case 'x':
|
511 |
case 'X':
|
512 |
case 'o':
|
513 |
num = va_arg(ap, unsigned);
|
514 |
_safe_sprintf(&buf, &buf_size, buf2, num);
|
515 |
break;
|
516 |
case 'd':
|
517 |
case 'c':
|
518 |
d = va_arg(ap, int);
|
519 |
_safe_sprintf(&buf, &buf_size, buf2, d);
|
520 |
break;
|
521 |
case 'f':
|
522 |
case 'F':
|
523 |
case 'e':
|
524 |
case 'E':
|
525 |
case 'g':
|
526 |
case 'G':
|
527 |
case 'a':
|
528 |
case 'A':
|
529 |
f = va_arg(ap, double);
|
530 |
_safe_sprintf(&buf, &buf_size, buf2, f);
|
531 |
break;
|
532 |
case 'p':
|
533 |
p = va_arg(ap, void *);
|
534 |
_safe_sprintf(&buf, &buf_size, buf2, p);
|
535 |
break;
|
536 |
default:
|
537 |
break;
|
538 |
}
|
539 |
|
540 |
cfustring_append_n(cfu_str, start, end - start + 1);
|
541 |
byte_count += end - start + 1;
|
542 |
cfustring_append(cfu_str, buf);
|
543 |
byte_count += strlen(buf);
|
544 |
fmt++;
|
545 |
start = end = fmt;
|
546 |
continue;
|
547 |
} else if (*fmt == 's') {
|
548 |
char *s = NULL;
|
549 |
size_t size = fmt - ptr + 1;
|
550 |
s = va_arg(ap, char *);
|
551 |
|
552 |
buf[0] = '\000';
|
553 |
|
554 |
_safe_strncpy(&buf2, &buf2_size, ptr, size);
|
555 |
buf2[size] = '\000';
|
556 |
|
557 |
_safe_sprintf(&buf, &buf_size, buf2, s);
|
558 |
|
559 |
if (ptr != start) {
|
560 |
cfustring_append_n(cfu_str, start, end - start + 1);
|
561 |
byte_count += end - start + 1;
|
562 |
}
|
563 |
if (s) {
|
564 |
cfustring_append(cfu_str, buf);
|
565 |
byte_count += strlen(buf);
|
566 |
} else {
|
567 |
s = "(null)";
|
568 |
cfustring_append(cfu_str, s);
|
569 |
byte_count += strlen(s);
|
570 |
}
|
571 |
fmt++;
|
572 |
start = end = fmt;
|
573 |
continue;
|
574 |
} else if (*fmt == ' ' || *fmt == '\t') {
|
575 |
cfustring_append_n(cfu_str, start, end - start + 1);
|
576 |
byte_count += end - start + 1;
|
577 |
fmt++;
|
578 |
start = end = fmt;
|
579 |
continue;
|
580 |
}
|
581 |
|
582 |
} else {
|
583 |
byte_count++;
|
584 |
end = fmt;
|
585 |
}
|
586 |
fmt++;
|
587 |
|
588 |
}
|
589 |
|
590 |
if (end != start) {
|
591 |
cfustring_append_n(cfu_str, start, end - start + 1);
|
592 |
byte_count += end - start + 1;
|
593 |
}
|
594 |
|
595 |
free(buf);
|
596 |
free(buf2);
|
597 |
|
598 |
return byte_count;
|
599 |
}
|
600 |
|
601 |
extern int
|
602 |
cfustring_destroy(cfustring_t *cfu_str) {
|
603 |
free(cfu_str->str);
|
604 |
free(cfu_str);
|
605 |
return 1;
|
606 |
}
|
607 |
|
608 |
extern char **
|
609 |
cfustring_c_str_split(const char *c_str, size_t *num_strings, size_t limit, ...) {
|
610 |
cfustring_t *cfu_str = cfustring_new_from_string(c_str);
|
611 |
char **rv = NULL;
|
612 |
va_list ap;
|
613 |
size_t num_seps = 0;
|
614 |
char *sep = NULL;
|
615 |
|
616 |
va_start(ap, limit);
|
617 |
sep = va_arg(ap, char *);
|
618 |
while (sep) {
|
619 |
num_seps++;
|
620 |
sep = va_arg(ap, char *);
|
621 |
}
|
622 |
va_end(ap);
|
623 |
|
624 |
va_start(ap, limit);
|
625 |
rv = __cfustring_split_to_raw(cfu_str, num_strings, num_seps, limit, ap);
|
626 |
va_end(ap);
|
627 |
|
628 |
cfustring_destroy(cfu_str);
|
629 |
|
630 |
return rv;
|
631 |
}
|