/[zanavi_public1]/navit/navit/maptool/libcfu-0.03-zanavi/src/cfustring.c
ZANavi

Contents of /navit/navit/maptool/libcfu-0.03-zanavi/src/cfustring.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (show annotations) (download)
Sat Mar 8 21:37:20 2014 UTC (10 years ago) by zoff99
File MIME type: text/plain
File size: 13879 byte(s)
new market version, lots of new features
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 }

   
Visit the ZANavi Wiki