Mercurial > repos > dawe > srf2fastq
comparison srf2fastq/io_lib-1.12.2/io_lib/vlen.c @ 0:d901c9f41a6a default tip
Migrated tool version 1.0.1 from old tool shed archive to new tool shed repository
author | dawe |
---|---|
date | Tue, 07 Jun 2011 17:48:05 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d901c9f41a6a |
---|---|
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <stdarg.h> | |
4 #include <sys/types.h> | |
5 #include <string.h> | |
6 | |
7 #include "io_lib/vlen.h" | |
8 #include "io_lib/os.h" | |
9 | |
10 #ifndef MAX | |
11 #define MAX(a,b) ((a)>(b)?(a):(b)) | |
12 #endif | |
13 | |
14 #ifndef ABS | |
15 #define ABS(a) ((a)>0?(a):-(a)) | |
16 #endif | |
17 | |
18 /* #define DEBUG_printf(a,n) printf(a,n) */ | |
19 #define DEBUG_printf(a,n) | |
20 | |
21 /* | |
22 * vlen: 27/10/95 written by James Bonfield, jkb@mrc-lmb.cam.ac.uk | |
23 * | |
24 * Given sprintf style of arguments this routine returns the maximum | |
25 * size of buffer needed to allocate to use with sprintf. It errs on | |
26 * the side of caution by being simplistic in its approach: we assume | |
27 * all numbers are of maximum length. | |
28 * | |
29 * Handles the usual type conversions (%[%diuaxXcfeEgGpns]), but not | |
30 * the 'wide' character conversions (%C and %S). | |
31 * Precision is handled in the correct formats, including %*.* | |
32 * notations. | |
33 * Additionally, some of the more dubious (but probably illegal) cases | |
34 * are supported (eg "%10%" will expand to " %" on many | |
35 * systems). | |
36 * | |
37 * We also assume that the largest integer and larger pointer are 64 | |
38 * bits, which at least covers the machines we'll need it for. | |
39 */ | |
40 int flen(char *fmt, ...) | |
41 { | |
42 va_list args; | |
43 | |
44 va_start(args, fmt); | |
45 return vflen(fmt, args); | |
46 } | |
47 | |
48 int vflen(char *fmt, va_list ap) | |
49 { | |
50 int len = 0; | |
51 char *cp, c; | |
52 long l; | |
53 int i; | |
54 double d; | |
55 | |
56 /* | |
57 * This code modifies 'ap', but we do not know if va_list is a structure | |
58 * or a pointer to an array so we do not know if it is a local variable | |
59 * or not. | |
60 * C99 gets around this by defining va_copy() to make copies of ap, but | |
61 * this does not exist on all systems. | |
62 * For now, I just assume that when va_list is a pointer the system also | |
63 * provides a va_copy macro to work around this problem. The only system | |
64 * I have seen needing this so far was Linux on AMD64. | |
65 */ | |
66 #if defined(NEED_VA_COPY) | |
67 va_list ap_local; | |
68 va_copy(ap_local, ap); | |
69 #define ap ap_local | |
70 #endif | |
71 | |
72 for(cp = fmt; *cp; cp++) { | |
73 switch(*cp) { | |
74 | |
75 /* A format specifier */ | |
76 case '%': { | |
77 char *endp; | |
78 long conv_len1=0, conv_len2=0, conv_len=0; | |
79 signed int arg_size; | |
80 | |
81 /* Firstly, strip the modifier flags (+-#0 and [space]) */ | |
82 for(; c=*++cp;) { | |
83 if ('#' == c) | |
84 len+=2; /* Worst case of "0x" */ | |
85 else if ('-' == c || '+' == c || ' ' == c) | |
86 len++; | |
87 else | |
88 break; | |
89 } | |
90 | |
91 /* Width specifier */ | |
92 l = strtol(cp, &endp, 10); | |
93 if (endp != cp) { | |
94 cp = endp; | |
95 conv_len = conv_len1 = l; | |
96 } else if (*cp == '*') { | |
97 conv_len = conv_len1 = (int)va_arg(ap, int); | |
98 cp++; | |
99 } | |
100 | |
101 /* Precision specifier */ | |
102 if ('.' == *cp) { | |
103 cp++; | |
104 conv_len2 = strtol(cp, &endp, 10); | |
105 if (endp != cp) { | |
106 cp = endp; | |
107 } else if (*cp == '*') { | |
108 conv_len2 = (int)va_arg(ap, int); | |
109 cp++; | |
110 } | |
111 conv_len = MAX(conv_len1, conv_len2); | |
112 } | |
113 | |
114 /* Short/long identifier */ | |
115 if ('h' == *cp) { | |
116 arg_size = -1; /* short */ | |
117 cp++; | |
118 } else if ('l' == *cp) { | |
119 arg_size = 1; /* long */ | |
120 cp++; | |
121 } else { | |
122 arg_size = 0; /* int */ | |
123 } | |
124 | |
125 /* The actual type */ | |
126 switch (*cp) { | |
127 case '%': | |
128 /* | |
129 * Not real ANSI I suspect, but we'll allow for the | |
130 * completely daft "%10%" example. | |
131 */ | |
132 len += MAX(conv_len1, 1); | |
133 break; | |
134 | |
135 case 'd': | |
136 case 'i': | |
137 case 'u': | |
138 case 'a': | |
139 case 'x': | |
140 case 'X': | |
141 /* Remember: char and short are sent as int on the stack */ | |
142 if (arg_size == -1) | |
143 l = (long)va_arg(ap, int); | |
144 else if (arg_size == 1) | |
145 l = va_arg(ap, long); | |
146 else | |
147 l = (long)va_arg(ap, int); | |
148 | |
149 DEBUG_printf("%d", l); | |
150 | |
151 /* | |
152 * No number can be more than 24 characters so we'll take | |
153 * the max of conv_len and 24 (23 is len(2^64) in octal). | |
154 * All that work above and we then go and estimate ;-), | |
155 * but it's needed incase someone does %500d. | |
156 */ | |
157 len += MAX(conv_len, 23); | |
158 break; | |
159 | |
160 case 'c': | |
161 i = va_arg(ap, int); | |
162 DEBUG_printf("%c", i); | |
163 /* | |
164 * Note that %10c and %.10c act differently. | |
165 * Besides, I think precision is not really allowed for %c. | |
166 */ | |
167 len += MAX(conv_len1, 1); | |
168 break; | |
169 | |
170 case 'f': | |
171 d = va_arg(ap, double); | |
172 DEBUG_printf("%f", d); | |
173 /* | |
174 * Maybe "Inf" or "NaN", but we'll not worry about that. | |
175 * Again, err on side of caution and take max of conv_len | |
176 * and max length of a double. The worst case I can | |
177 * think of is 317 characters (-1[308 zeros].000000) | |
178 * without using precision codes. That's horrid. I | |
179 * cheat and either use 317 or 15 depending on how | |
180 * large the number is as I reckon 99% of floats | |
181 * aren't that long. | |
182 */ | |
183 l = (ABS(d) > 1000000) ? 317 : 15; | |
184 l = MAX(l, conv_len1 + 2); | |
185 if (conv_len2) l += conv_len2 - 6; | |
186 len += l; | |
187 break; | |
188 | |
189 case 'e': | |
190 case 'E': | |
191 case 'g': | |
192 case 'G': | |
193 d = va_arg(ap, double); | |
194 DEBUG_printf("%g", d); | |
195 /* | |
196 * Maybe "Inf" or "NaN", but we'll not worry about that | |
197 * Again, err on side of caution and take max of conv_len | |
198 * and max length of a double (which defaults to only | |
199 * '-' + 6 + '.' + 'E[+-]xxx' == 13. | |
200 */ | |
201 len += MAX(conv_len, 13); | |
202 break; | |
203 | |
204 case 'p': | |
205 l = (long)va_arg(ap, void *); | |
206 /* | |
207 * Max pointer is 64bits == 16 chars (on alpha), | |
208 * == 20 with + "0x". | |
209 */ | |
210 DEBUG_printf("%p", (void *)l); | |
211 len += MAX(conv_len, 20); | |
212 break; | |
213 | |
214 case 'n': | |
215 /* produces no output */ | |
216 break; | |
217 | |
218 case 's': { | |
219 char *s = (char *)va_arg(ap, char *); | |
220 DEBUG_printf("%s", s); | |
221 | |
222 if (!conv_len2) { | |
223 len += MAX(conv_len, (int)strlen(s)); | |
224 } else { | |
225 len += conv_len; | |
226 } | |
227 break; | |
228 } | |
229 | |
230 default: | |
231 /* wchar_t types of 'C' and 'S' aren't supported */ | |
232 DEBUG_printf("Arg is %c\n", *cp); | |
233 } | |
234 | |
235 } | |
236 | |
237 case '\0': | |
238 break; | |
239 | |
240 default: | |
241 DEBUG_printf("%c", *cp); | |
242 len++; | |
243 } | |
244 } | |
245 | |
246 va_end(ap); | |
247 | |
248 return len+1; /* one for the null character */ | |
249 } | |
250 | |
251 #if 0 | |
252 int main() { | |
253 int l; | |
254 char buf[10000]; | |
255 | |
256 sprintf(buf, "d: %d\n", 500); | |
257 l = flen("d: %d\n", 500); | |
258 printf("%d %d\n\n", strlen(buf), l); | |
259 | |
260 sprintf(buf, ""); | |
261 l = flen(""); | |
262 printf("%d %d\n\n", strlen(buf), l); | |
263 | |
264 sprintf(buf, "%s\n","test"); | |
265 l = flen("%s\n", "test"); | |
266 printf("%d %d\n\n", strlen(buf), l); | |
267 | |
268 sprintf(buf, "%c\n", 'a'); | |
269 l = flen("%c\n", 'a'); | |
270 printf("%d %d\n\n", strlen(buf), l); | |
271 | |
272 sprintf(buf, "%31.30f\n", -9999.99); | |
273 l = flen("%31.30f\n", -9999.99); | |
274 printf("%d %d\n\n", strlen(buf), l); | |
275 | |
276 sprintf(buf, "%f\n", -1e308); | |
277 l = flen("%f\n", -1e308); | |
278 printf("%d %d\n\n", strlen(buf), l); | |
279 | |
280 sprintf(buf, "%.9f\n", -1e308); | |
281 l = flen("%.9f\n", -1e308); | |
282 printf("%d %d\n\n", strlen(buf), l); | |
283 | |
284 sprintf(buf, "%10.20f\n", -1.999222333); | |
285 l = flen("%10.20f\n", -1.999222333); | |
286 printf("%d %d\n\n", strlen(buf), l); | |
287 | |
288 sprintf(buf, "%#g\n", -3.14159265358e-222); | |
289 l = flen("%#g\n", -3.1415927e-222); | |
290 printf("%d %d\n\n", strlen(buf), l); | |
291 | |
292 sprintf(buf, "%e\n", -123456789123456789.1); | |
293 l = flen("%e\n", -123456789123456789.1); | |
294 printf("%d %d\n\n", strlen(buf), l); | |
295 | |
296 sprintf(buf, "%c %f %d %s %c %g %ld %s\n", 'a', 3.1, 9, "one", 'b', 4.2, 9, "two"); | |
297 l = flen("%c %f %d %s %c %g %ld %s\n", 'a', 3.1, 9, "one", 'b', 4.2, 9, "two"); | |
298 printf("%d %d\n\n", strlen(buf), l); | |
299 | |
300 sprintf(buf, "%*.*e %*c\n", 10, 5, 9.0, 20, 'x'); | |
301 l = flen("%*.*e %*c\n", 10, 5, 9.0, 20, 'x'); | |
302 printf("%d %d\n\n", strlen(buf), l); | |
303 | |
304 sprintf(buf, "%10c\n", 'z'); | |
305 l = flen("%10c\n", 'z'); | |
306 printf("%d %d\n\n", strlen(buf), l); | |
307 | |
308 sprintf(buf, "%.10c\n", 'z'); | |
309 l = flen("%.10c\n", 'z'); | |
310 printf("%d %d\n\n", strlen(buf), l); | |
311 | |
312 sprintf(buf, "%10d\n", 'z'); | |
313 l = flen("%10d\n", 'z'); | |
314 printf("%d %d\n\n", strlen(buf), l); | |
315 | |
316 sprintf(buf, "%.10d\n", 'z'); | |
317 l = flen("%.10d\n", 'z'); | |
318 printf("%d %d\n\n", strlen(buf), l); | |
319 | |
320 sprintf(buf, "%10%\n"); | |
321 l = flen("%10%\n"); | |
322 printf("%d %d\n\n", strlen(buf), l); | |
323 | |
324 sprintf(buf, "%.10%\n"); | |
325 l = flen("%.10%\n"); | |
326 printf("%d %d\n\n", strlen(buf), l); | |
327 | |
328 sprintf(buf, "%s\n", "0123456789"); | |
329 l = flen("%s\n", "0123456789"); | |
330 printf("%d %d\n\n", strlen(buf), l); | |
331 | |
332 sprintf(buf, "%5s\n", "0123456789"); | |
333 l = flen("%5s\n", "0123456789"); | |
334 printf("%d %d\n\n", strlen(buf), l); | |
335 | |
336 sprintf(buf, "%50s\n", "0123456789"); | |
337 l = flen("%50s\n", "0123456789"); | |
338 printf("%d %d\n\n", strlen(buf), l); | |
339 | |
340 sprintf(buf, "%.5s\n", "0123456789"); | |
341 l = flen("%.5s\n", "0123456789"); | |
342 printf("%d %d\n\n", strlen(buf), l); | |
343 | |
344 sprintf(buf, "%.50s\n", "0123456789"); | |
345 l = flen("%.50s\n", "0123456789"); | |
346 printf("%d %d\n\n", strlen(buf), l); | |
347 | |
348 sprintf(buf, "%5.50s\n", "0123456789"); | |
349 l = flen("%5.50s\n", "0123456789"); | |
350 printf("%d %d\n\n", strlen(buf), l); | |
351 | |
352 sprintf(buf, "%50.5s\n", "0123456789"); | |
353 l = flen("%50.5s\n", "0123456789"); | |
354 printf("%d %d\n\n", strlen(buf), l); | |
355 | |
356 return 0; | |
357 } | |
358 #endif |