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 +/