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