NVBIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
kstring.h
Go to the documentation of this file.
1 /* The MIT License
2 
3  Copyright (c) by Attractive Chaos <attractor@live.co.uk>
4 
5  Permission is hereby granted, free of charge, to any person obtaining
6  a copy of this software and associated documentation files (the
7  "Software"), to deal in the Software without restriction, including
8  without limitation the rights to use, copy, modify, merge, publish,
9  distribute, sublicense, and/or sell copies of the Software, and to
10  permit persons to whom the Software is furnished to do so, subject to
11  the following conditions:
12 
13  The above copyright notice and this permission notice shall be
14  included in all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  SOFTWARE.
24 */
25 
26 #ifndef KSTRING_H
27 #define KSTRING_H
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 
35 #ifndef kroundup32
36 #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
37 #endif
38 
39 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
40 #define KS_ATTR_PRINTF(fmt, arg) __attribute__((__format__ (__printf__, fmt, arg)))
41 #else
42 #define KS_ATTR_PRINTF(fmt, arg)
43 #endif
44 
45 
46 /* kstring_t is a simple non-opaque type whose fields are likely to be
47  * used directly by user code (but see also ks_str() and ks_len() below).
48  * A kstring_t object is initialised by either of
49  * kstring_t str = { 0, 0, NULL };
50  * kstring_t str; ...; str.l = str.m = 0; str.s = NULL;
51  * and either ownership of the underlying buffer should be given away before
52  * the object disappears (see ks_release() below) or the kstring_t should be
53  * destroyed with free(str.s); */
54 #ifndef KSTRING_T
55 #define KSTRING_T kstring_t
56 typedef struct __kstring_t {
57  size_t l, m;
58  char *s;
59 } kstring_t;
60 #endif
61 
62 typedef struct {
63  uint64_t tab[4];
64  int sep, finished;
65  const char *p; // end of the current token
66 } ks_tokaux_t;
67 
68 #ifdef __cplusplus
69 extern "C" {
70 #endif
71 
72  int kvsprintf(kstring_t *s, const char *fmt, va_list ap) KS_ATTR_PRINTF(2,0);
73  int ksprintf(kstring_t *s, const char *fmt, ...) KS_ATTR_PRINTF(2,3);
74  int ksplit_core(char *s, int delimiter, int *_max, int **_offsets);
75  char *kstrstr(const char *str, const char *pat, int **_prep);
76  char *kstrnstr(const char *str, const char *pat, int n, int **_prep);
77  void *kmemmem(const void *_str, int n, const void *_pat, int m, int **_prep);
78 
79  /* kstrtok() is similar to strtok_r() except that str is not
80  * modified and both str and sep can be NULL. For efficiency, it is
81  * actually recommended to set both to NULL in the subsequent calls
82  * if sep is not changed. */
83  char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux);
84 
85 #ifdef __cplusplus
86 }
87 #endif
88 
89 static inline int ks_resize(kstring_t *s, size_t size)
90 {
91  if (s->m < size) {
92  char *tmp;
93  s->m = size;
94  kroundup32(s->m);
95  if ((tmp = (char*)realloc(s->s, s->m)))
96  s->s = tmp;
97  else
98  return -1;
99  }
100  return 0;
101 }
102 
103 static inline char *ks_str(kstring_t *s)
104 {
105  return s->s;
106 }
107 
108 static inline size_t ks_len(kstring_t *s)
109 {
110  return s->l;
111 }
112 
113 // Give ownership of the underlying buffer away to something else (making
114 // that something else responsible for freeing it), leaving the kstring_t
115 // empty and ready to be used again, or ready to go out of scope without
116 // needing free(str.s) to prevent a memory leak.
117 static inline char *ks_release(kstring_t *s)
118 {
119  char *ss = s->s;
120  s->l = s->m = 0;
121  s->s = NULL;
122  return ss;
123 }
124 
125 static inline int kputsn(const char *p, int l, kstring_t *s)
126 {
127  if (s->l + l + 1 >= s->m) {
128  char *tmp;
129  s->m = s->l + l + 2;
130  kroundup32(s->m);
131  if ((tmp = (char*)realloc(s->s, s->m)))
132  s->s = tmp;
133  else
134  return EOF;
135  }
136  memcpy(s->s + s->l, p, l);
137  s->l += l;
138  s->s[s->l] = 0;
139  return l;
140 }
141 
142 static inline int kputs(const char *p, kstring_t *s)
143 {
144  return kputsn(p, strlen(p), s);
145 }
146 
147 static inline int kputc(int c, kstring_t *s)
148 {
149  if (s->l + 1 >= s->m) {
150  char *tmp;
151  s->m = s->l + 2;
152  kroundup32(s->m);
153  if ((tmp = (char*)realloc(s->s, s->m)))
154  s->s = tmp;
155  else
156  return EOF;
157  }
158  s->s[s->l++] = c;
159  s->s[s->l] = 0;
160  return c;
161 }
162 
163 static inline int kputc_(int c, kstring_t *s)
164 {
165  if (s->l + 1 > s->m) {
166  char *tmp;
167  s->m = s->l + 1;
168  kroundup32(s->m);
169  if ((tmp = (char*)realloc(s->s, s->m)))
170  s->s = tmp;
171  else
172  return EOF;
173  }
174  s->s[s->l++] = c;
175  return 1;
176 }
177 
178 static inline int kputsn_(const void *p, int l, kstring_t *s)
179 {
180  if (s->l + l > s->m) {
181  char *tmp;
182  s->m = s->l + l;
183  kroundup32(s->m);
184  if ((tmp = (char*)realloc(s->s, s->m)))
185  s->s = tmp;
186  else
187  return EOF;
188  }
189  memcpy(s->s + s->l, p, l);
190  s->l += l;
191  return l;
192 }
193 
194 static inline int kputw(int c, kstring_t *s)
195 {
196  char buf[16];
197  int i, l = 0;
198  unsigned int x = c;
199  if (c < 0) x = -x;
200  do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0);
201  if (c < 0) buf[l++] = '-';
202  if (s->l + l + 1 >= s->m) {
203  char *tmp;
204  s->m = s->l + l + 2;
205  kroundup32(s->m);
206  if ((tmp = (char*)realloc(s->s, s->m)))
207  s->s = tmp;
208  else
209  return EOF;
210  }
211  for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
212  s->s[s->l] = 0;
213  return 0;
214 }
215 
216 static inline int kputuw(unsigned c, kstring_t *s)
217 {
218  char buf[16];
219  int l, i;
220  unsigned x;
221  if (c == 0) return kputc('0', s);
222  for (l = 0, x = c; x > 0; x /= 10) buf[l++] = x%10 + '0';
223  if (s->l + l + 1 >= s->m) {
224  char *tmp;
225  s->m = s->l + l + 2;
226  kroundup32(s->m);
227  if ((tmp = (char*)realloc(s->s, s->m)))
228  s->s = tmp;
229  else
230  return EOF;
231  }
232  for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
233  s->s[s->l] = 0;
234  return 0;
235 }
236 
237 static inline int kputl(long c, kstring_t *s)
238 {
239  char buf[32];
240  int i, l = 0;
241  unsigned long x = c;
242  if (c < 0) x = -x;
243  do { buf[l++] = x%10 + '0'; x /= 10; } while (x > 0);
244  if (c < 0) buf[l++] = '-';
245  if (s->l + l + 1 >= s->m) {
246  char *tmp;
247  s->m = s->l + l + 2;
248  kroundup32(s->m);
249  if ((tmp = (char*)realloc(s->s, s->m)))
250  s->s = tmp;
251  else
252  return EOF;
253  }
254  for (i = l - 1; i >= 0; --i) s->s[s->l++] = buf[i];
255  s->s[s->l] = 0;
256  return 0;
257 }
258 
259 /*
260  * Returns 's' split by delimiter, with *n being the number of components;
261  * NULL on failue.
262  */
263 static inline int *ksplit(kstring_t *s, int delimiter, int *n)
264 {
265  int max = 0, *offsets = 0;
266  *n = ksplit_core(s->s, delimiter, &max, &offsets);
267  return offsets;
268 }
269 
270 #endif