dc20faeac9fef21c88813c34f9f42ac6c69d449d
[samtools.git] / kstring.c
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <string.h>
5 #include "kstring.h"
6
7 int ksprintf(kstring_t *s, const char *fmt, ...)
8 {
9         va_list ap;
10         int l;
11         va_start(ap, fmt);
12         l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap); // This line does not work with glibc 2.0. See `man snprintf'.
13         va_end(ap);
14         if (l + 1 > s->m - s->l) {
15                 s->m = s->l + l + 2;
16                 kroundup32(s->m);
17                 s->s = (char*)realloc(s->s, s->m);
18                 va_start(ap, fmt);
19                 l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap);
20         }
21         va_end(ap);
22         s->l += l;
23         return l;
24 }
25
26 // s MUST BE a null terminated string; l = strlen(s)
27 int ksplit_core(char *s, int delimiter, int *_max, int **_offsets)
28 {
29         int i, n, max, last_char, last_start, *offsets, l;
30         n = 0; max = *_max; offsets = *_offsets;
31         l = strlen(s);
32         
33 #define __ksplit_aux do {                                                                                               \
34                 if (_offsets) {                                                                                                 \
35                         s[i] = 0;                                                                                                       \
36                         if (n == max) {                                                                                         \
37                                 max = max? max<<1 : 2;                                                                  \
38                                 offsets = (int*)realloc(offsets, sizeof(int) * max);    \
39                         }                                                                                                                       \
40                         offsets[n++] = last_start;                                                                      \
41                 } else ++n;                                                                                                             \
42         } while (0)
43
44         for (i = 0, last_char = last_start = 0; i <= l; ++i) {
45                 if (delimiter == 0) {
46                         if (isspace(s[i]) || s[i] == 0) {
47                                 if (isgraph(last_char)) __ksplit_aux; // the end of a field
48                         } else {
49                                 if (isspace(last_char) || last_char == 0) last_start = i;
50                         }
51                 } else {
52                         if (s[i] == delimiter || s[i] == 0) {
53                                 if (last_char != 0 && last_char != delimiter) __ksplit_aux; // the end of a field
54                         } else {
55                                 if (last_char == delimiter || last_char == 0) last_start = i;
56                         }
57                 }
58                 last_char = s[i];
59         }
60         *_max = max; *_offsets = offsets;
61         return n;
62 }
63
64 #ifdef KSTRING_MAIN
65 #include <stdio.h>
66 int main()
67 {
68         kstring_t *s;
69         int *fields, n, i;
70         s = (kstring_t*)calloc(1, sizeof(kstring_t));
71         // test ksprintf()
72         ksprintf(s, " abcdefg:    %d ", 100);
73         printf("'%s'\n", s->s);
74         // test ksplit()
75         fields = ksplit(s, 0, &n);
76         for (i = 0; i < n; ++i)
77                 printf("field[%d] = '%s'\n", i, s->s + fields[i]);
78         free(s);
79         return 0;
80 }
81 #endif