Mercurial > repos > youngkim > ezbamqc
comparison ezBAMQC/src/htslib/cram/vlen.c @ 0:dfa3745e5fd8
Uploaded
author | youngkim |
---|---|
date | Thu, 24 Mar 2016 17:12:52 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:dfa3745e5fd8 |
---|---|
1 /* | |
2 Author: James Bonfield (jkb@sanger.ac.uk) | |
3 | |
4 Copyright (c) 1995-1996 MEDICAL RESEARCH COUNCIL | |
5 All rights reserved | |
6 | |
7 Redistribution and use in source and binary forms, with or without | |
8 modification, are permitted provided that the following conditions are met: | |
9 | |
10 1 Redistributions of source code must retain the above copyright notice, | |
11 this list of conditions and the following disclaimer. | |
12 | |
13 2 Redistributions in binary form must reproduce the above copyright notice, | |
14 this list of conditions and the following disclaimer in the documentation | |
15 and/or other materials provided with the distribution. | |
16 | |
17 3 Neither the name of the MEDICAL RESEARCH COUNCIL, THE LABORATORY OF | |
18 MOLECULAR BIOLOGY nor the names of its contributors may be used to endorse or | |
19 promote products derived from this software without specific prior written | |
20 permission. | |
21 | |
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 */ | |
33 | |
34 /* | |
35 Copyright (c) 2004, 2009, 2011-2012 Genome Research Ltd. | |
36 | |
37 Author: James Bonfield <jkb@sanger.ac.uk> | |
38 | |
39 Redistribution and use in source and binary forms, with or without | |
40 modification, are permitted provided that the following conditions are met: | |
41 | |
42 1. Redistributions of source code must retain the above copyright notice, | |
43 this list of conditions and the following disclaimer. | |
44 | |
45 2. Redistributions in binary form must reproduce the above copyright notice, | |
46 this list of conditions and the following disclaimer in the documentation | |
47 and/or other materials provided with the distribution. | |
48 | |
49 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger | |
50 Institute nor the names of its contributors may be used to endorse or promote | |
51 products derived from this software without specific prior written permission. | |
52 | |
53 THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND | |
54 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
55 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
56 DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE | |
57 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
58 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
59 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
60 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
61 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
62 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
63 */ | |
64 | |
65 #ifdef HAVE_CONFIG_H | |
66 #include "io_lib_config.h" | |
67 #endif | |
68 | |
69 #include <stdio.h> | |
70 #include <stdlib.h> | |
71 #include <stdarg.h> | |
72 #include <sys/types.h> | |
73 #include <string.h> | |
74 | |
75 #include "cram/vlen.h" | |
76 #include "cram/os.h" | |
77 | |
78 #ifndef MAX | |
79 #define MAX(a,b) ((a)>(b)?(a):(b)) | |
80 #endif | |
81 | |
82 #ifndef ABS | |
83 #define ABS(a) ((a)>0?(a):-(a)) | |
84 #endif | |
85 | |
86 /* #define DEBUG_printf(a,n) printf(a,n) */ | |
87 #define DEBUG_printf(a,n) | |
88 | |
89 /* | |
90 * vlen: 27/10/95 written by James Bonfield, jkb@mrc-lmb.cam.ac.uk | |
91 * | |
92 * Given sprintf style of arguments this routine returns the maximum | |
93 * size of buffer needed to allocate to use with sprintf. It errs on | |
94 * the side of caution by being simplistic in its approach: we assume | |
95 * all numbers are of maximum length. | |
96 * | |
97 * Handles the usual type conversions (%[%diuaxXcfeEgGpns]), but not | |
98 * the 'wide' character conversions (%C and %S). | |
99 * Precision is handled in the correct formats, including %*.* | |
100 * notations. | |
101 * Additionally, some of the more dubious (but probably illegal) cases | |
102 * are supported (eg "%10%" will expand to " %" on many | |
103 * systems). | |
104 * | |
105 * We also assume that the largest integer and larger pointer are 64 | |
106 * bits, which at least covers the machines we'll need it for. | |
107 */ | |
108 int flen(char *fmt, ...) | |
109 { | |
110 va_list args; | |
111 | |
112 va_start(args, fmt); | |
113 return vflen(fmt, args); | |
114 } | |
115 | |
116 int vflen(char *fmt, va_list ap) | |
117 { | |
118 int len = 0; | |
119 char *cp, c; | |
120 long long l; | |
121 int i; | |
122 double d; | |
123 | |
124 /* | |
125 * This code modifies 'ap', but we do not know if va_list is a structure | |
126 * or a pointer to an array so we do not know if it is a local variable | |
127 * or not. | |
128 * C99 gets around this by defining va_copy() to make copies of ap, but | |
129 * this does not exist on all systems. | |
130 * For now, I just assume that when va_list is a pointer the system also | |
131 * provides a va_copy macro to work around this problem. The only system | |
132 * I have seen needing this so far was Linux on AMD64. | |
133 */ | |
134 #if defined(HAVE_VA_COPY) | |
135 va_list ap_local; | |
136 va_copy(ap_local, ap); | |
137 # define ap ap_local | |
138 #endif | |
139 | |
140 for(cp = fmt; *cp; cp++) { | |
141 switch(*cp) { | |
142 | |
143 /* A format specifier */ | |
144 case '%': { | |
145 char *endp; | |
146 long conv_len1=0, conv_len2=0, conv_len=0; | |
147 signed int arg_size; | |
148 | |
149 /* Firstly, strip the modifier flags (+-#0 and [space]) */ | |
150 for(; (c=*++cp);) { | |
151 if ('#' == c) | |
152 len+=2; /* Worst case of "0x" */ | |
153 else if ('-' == c || '+' == c || ' ' == c) | |
154 len++; | |
155 else | |
156 break; | |
157 } | |
158 | |
159 /* Width specifier */ | |
160 l = strtol(cp, &endp, 10); | |
161 if (endp != cp) { | |
162 cp = endp; | |
163 conv_len = conv_len1 = l; | |
164 } else if (*cp == '*') { | |
165 conv_len = conv_len1 = (int)va_arg(ap, int); | |
166 cp++; | |
167 } | |
168 | |
169 /* Precision specifier */ | |
170 if ('.' == *cp) { | |
171 cp++; | |
172 conv_len2 = strtol(cp, &endp, 10); | |
173 if (endp != cp) { | |
174 cp = endp; | |
175 } else if (*cp == '*') { | |
176 conv_len2 = (int)va_arg(ap, int); | |
177 cp++; | |
178 } | |
179 conv_len = MAX(conv_len1, conv_len2); | |
180 } | |
181 | |
182 /* Short/long identifier */ | |
183 if ('h' == *cp) { | |
184 arg_size = -1; /* short */ | |
185 cp++; | |
186 } else if ('l' == *cp) { | |
187 arg_size = 1; /* long */ | |
188 cp++; | |
189 if ('l' == *cp) { | |
190 arg_size = 2; /* long long */ | |
191 cp++; | |
192 } | |
193 } else { | |
194 arg_size = 0; /* int */ | |
195 } | |
196 | |
197 /* The actual type */ | |
198 switch (*cp) { | |
199 case '%': | |
200 /* | |
201 * Not real ANSI I suspect, but we'll allow for the | |
202 * completely daft "%10%" example. | |
203 */ | |
204 len += MAX(conv_len1, 1); | |
205 break; | |
206 | |
207 case 'd': | |
208 case 'i': | |
209 case 'u': | |
210 case 'a': | |
211 case 'x': | |
212 case 'X': | |
213 /* Remember: char and short are sent as int on the stack */ | |
214 if (arg_size == -1) | |
215 l = (long)va_arg(ap, int); | |
216 else if (arg_size == 1) | |
217 l = va_arg(ap, long); | |
218 else if (arg_size == 2) | |
219 l = va_arg(ap, long long); | |
220 else | |
221 l = (long)va_arg(ap, int); | |
222 | |
223 DEBUG_printf("%d", l); | |
224 | |
225 /* | |
226 * No number can be more than 24 characters so we'll take | |
227 * the max of conv_len and 24 (23 is len(2^64) in octal). | |
228 * All that work above and we then go and estimate ;-), | |
229 * but it's needed incase someone does %500d. | |
230 */ | |
231 len += MAX(conv_len, 23); | |
232 break; | |
233 | |
234 case 'c': | |
235 i = va_arg(ap, int); | |
236 DEBUG_printf("%c", i); | |
237 /* | |
238 * Note that %10c and %.10c act differently. | |
239 * Besides, I think precision is not really allowed for %c. | |
240 */ | |
241 len += MAX(conv_len1, i>=0x80 ?MB_CUR_MAX :1); | |
242 break; | |
243 | |
244 case 'f': | |
245 d = va_arg(ap, double); | |
246 DEBUG_printf("%f", d); | |
247 /* | |
248 * Maybe "Inf" or "NaN", but we'll not worry about that. | |
249 * Again, err on side of caution and take max of conv_len | |
250 * and max length of a double. The worst case I can | |
251 * think of is 317 characters (-1[308 zeros].000000) | |
252 * without using precision codes. That's horrid. I | |
253 * cheat and either use 317 or 15 depending on how | |
254 * large the number is as I reckon 99% of floats | |
255 * aren't that long. | |
256 */ | |
257 l = (ABS(d) > 1000000) ? 317 : 15; | |
258 l = MAX(l, conv_len1 + 2); | |
259 if (conv_len2) l += conv_len2 - 6; | |
260 len += l; | |
261 break; | |
262 | |
263 case 'e': | |
264 case 'E': | |
265 case 'g': | |
266 case 'G': | |
267 d = va_arg(ap, double); | |
268 DEBUG_printf("%g", d); | |
269 /* | |
270 * Maybe "Inf" or "NaN", but we'll not worry about that | |
271 * Again, err on side of caution and take max of conv_len | |
272 * and max length of a double (which defaults to only | |
273 * '-' + 6 + '.' + 'E[+-]xxx' == 13. | |
274 */ | |
275 len += MAX(conv_len, 13); | |
276 break; | |
277 | |
278 case 'p': | |
279 l = (long)va_arg(ap, void *); | |
280 /* | |
281 * Max pointer is 64bits == 16 chars (on alpha), | |
282 * == 20 with + "0x". | |
283 */ | |
284 DEBUG_printf("%p", (void *)l); | |
285 len += MAX(conv_len, 20); | |
286 break; | |
287 | |
288 case 'n': | |
289 /* produces no output */ | |
290 break; | |
291 | |
292 case 's': { | |
293 char *s = (char *)va_arg(ap, char *); | |
294 DEBUG_printf("%s", s); | |
295 | |
296 if (!conv_len2) { | |
297 len += MAX(conv_len, (int)strlen(s)); | |
298 } else { | |
299 len += conv_len; | |
300 } | |
301 break; | |
302 } | |
303 | |
304 default: | |
305 /* wchar_t types of 'C' and 'S' aren't supported */ | |
306 DEBUG_printf("Arg is %c\n", *cp); | |
307 } | |
308 | |
309 } | |
310 | |
311 case '\0': | |
312 break; | |
313 | |
314 default: | |
315 DEBUG_printf("%c", *cp); | |
316 len++; | |
317 } | |
318 } | |
319 | |
320 va_end(ap); | |
321 | |
322 return len+1; /* one for the null character */ | |
323 } | |
324 | |
325 #if 0 | |
326 int main() { | |
327 int l; | |
328 char buf[10000]; | |
329 | |
330 sprintf(buf, "d: %d\n", 500); | |
331 l = flen("d: %d\n", 500); | |
332 printf("%d %d\n\n", strlen(buf), l); | |
333 | |
334 sprintf(buf, ""); | |
335 l = flen(""); | |
336 printf("%d %d\n\n", strlen(buf), l); | |
337 | |
338 sprintf(buf, "%s\n","test"); | |
339 l = flen("%s\n", "test"); | |
340 printf("%d %d\n\n", strlen(buf), l); | |
341 | |
342 sprintf(buf, "%c\n", 'a'); | |
343 l = flen("%c\n", 'a'); | |
344 printf("%d %d\n\n", strlen(buf), l); | |
345 | |
346 sprintf(buf, "%31.30f\n", -9999.99); | |
347 l = flen("%31.30f\n", -9999.99); | |
348 printf("%d %d\n\n", strlen(buf), l); | |
349 | |
350 sprintf(buf, "%f\n", -1e308); | |
351 l = flen("%f\n", -1e308); | |
352 printf("%d %d\n\n", strlen(buf), l); | |
353 | |
354 sprintf(buf, "%.9f\n", -1e308); | |
355 l = flen("%.9f\n", -1e308); | |
356 printf("%d %d\n\n", strlen(buf), l); | |
357 | |
358 sprintf(buf, "%10.20f\n", -1.999222333); | |
359 l = flen("%10.20f\n", -1.999222333); | |
360 printf("%d %d\n\n", strlen(buf), l); | |
361 | |
362 sprintf(buf, "%#g\n", -3.14159265358e-222); | |
363 l = flen("%#g\n", -3.1415927e-222); | |
364 printf("%d %d\n\n", strlen(buf), l); | |
365 | |
366 sprintf(buf, "%e\n", -123456789123456789.1); | |
367 l = flen("%e\n", -123456789123456789.1); | |
368 printf("%d %d\n\n", strlen(buf), l); | |
369 | |
370 sprintf(buf, "%c %f %d %s %c %g %ld %s\n", 'a', 3.1, 9, "one", 'b', 4.2, 9, "two"); | |
371 l = flen("%c %f %d %s %c %g %ld %s\n", 'a', 3.1, 9, "one", 'b', 4.2, 9, "two"); | |
372 printf("%d %d\n\n", strlen(buf), l); | |
373 | |
374 sprintf(buf, "%*.*e %*c\n", 10, 5, 9.0, 20, 'x'); | |
375 l = flen("%*.*e %*c\n", 10, 5, 9.0, 20, 'x'); | |
376 printf("%d %d\n\n", strlen(buf), l); | |
377 | |
378 sprintf(buf, "%10c\n", 'z'); | |
379 l = flen("%10c\n", 'z'); | |
380 printf("%d %d\n\n", strlen(buf), l); | |
381 | |
382 sprintf(buf, "%.10c\n", 'z'); | |
383 l = flen("%.10c\n", 'z'); | |
384 printf("%d %d\n\n", strlen(buf), l); | |
385 | |
386 sprintf(buf, "%10d\n", 'z'); | |
387 l = flen("%10d\n", 'z'); | |
388 printf("%d %d\n\n", strlen(buf), l); | |
389 | |
390 sprintf(buf, "%.10d\n", 'z'); | |
391 l = flen("%.10d\n", 'z'); | |
392 printf("%d %d\n\n", strlen(buf), l); | |
393 | |
394 sprintf(buf, "%10%\n"); | |
395 l = flen("%10%\n"); | |
396 printf("%d %d\n\n", strlen(buf), l); | |
397 | |
398 sprintf(buf, "%.10%\n"); | |
399 l = flen("%.10%\n"); | |
400 printf("%d %d\n\n", strlen(buf), l); | |
401 | |
402 sprintf(buf, "%s\n", "0123456789"); | |
403 l = flen("%s\n", "0123456789"); | |
404 printf("%d %d\n\n", strlen(buf), l); | |
405 | |
406 sprintf(buf, "%5s\n", "0123456789"); | |
407 l = flen("%5s\n", "0123456789"); | |
408 printf("%d %d\n\n", strlen(buf), l); | |
409 | |
410 sprintf(buf, "%50s\n", "0123456789"); | |
411 l = flen("%50s\n", "0123456789"); | |
412 printf("%d %d\n\n", strlen(buf), l); | |
413 | |
414 sprintf(buf, "%.5s\n", "0123456789"); | |
415 l = flen("%.5s\n", "0123456789"); | |
416 printf("%d %d\n\n", strlen(buf), l); | |
417 | |
418 sprintf(buf, "%.50s\n", "0123456789"); | |
419 l = flen("%.50s\n", "0123456789"); | |
420 printf("%d %d\n\n", strlen(buf), l); | |
421 | |
422 sprintf(buf, "%5.50s\n", "0123456789"); | |
423 l = flen("%5.50s\n", "0123456789"); | |
424 printf("%d %d\n\n", strlen(buf), l); | |
425 | |
426 sprintf(buf, "%50.5s\n", "0123456789"); | |
427 l = flen("%50.5s\n", "0123456789"); | |
428 printf("%d %d\n\n", strlen(buf), l); | |
429 | |
430 return 0; | |
431 } | |
432 #endif |