diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srf2fastq/io_lib-1.12.2/io_lib/vlen.c	Tue Jun 07 17:48:05 2011 -0400
@@ -0,0 +1,358 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "io_lib/vlen.h"
+#include "io_lib/os.h"
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef ABS
+#define ABS(a) ((a)>0?(a):-(a))
+#endif
+
+/* #define DEBUG_printf(a,n) printf(a,n) */
+#define DEBUG_printf(a,n)
+
+/*
+ * vlen: 27/10/95 written by James Bonfield, jkb@mrc-lmb.cam.ac.uk
+ *
+ * Given sprintf style of arguments this routine returns the maximum
+ * size of buffer needed to allocate to use with sprintf. It errs on
+ * the side of caution by being simplistic in its approach: we assume
+ * all numbers are of maximum length.
+ *
+ * Handles the usual type conversions (%[%diuaxXcfeEgGpns]), but not
+ * the 'wide' character conversions (%C and %S).
+ * Precision is handled in the correct formats, including %*.*
+ * notations.
+ * Additionally, some of the more dubious (but probably illegal) cases
+ * are supported (eg "%10%" will expand to "         %" on many
+ * systems).
+ *
+ * We also assume that the largest integer and larger pointer are 64
+ * bits, which at least covers the machines we'll need it for.
+ */
+int flen(char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    return vflen(fmt, args);
+}
+
+int vflen(char *fmt, va_list ap)
+{
+    int len = 0;
+    char *cp, c;
+    long l;
+    int i;
+    double d; 
+
+    /*
+     * This code modifies 'ap', but we do not know if va_list is a structure
+     * or a pointer to an array so we do not know if it is a local variable
+     * or not.
+     * C99 gets around this by defining va_copy() to make copies of ap, but
+     * this does not exist on all systems.
+     * For now, I just assume that when va_list is a pointer the system also
+     * provides a va_copy macro to work around this problem. The only system
+     * I have seen needing this so far was Linux on AMD64.
+     */
+#if defined(NEED_VA_COPY)
+    va_list ap_local;
+    va_copy(ap_local, ap);
+    #define ap ap_local
+#endif
+
+    for(cp = fmt; *cp; cp++) {
+	switch(*cp) {
+
+	/* A format specifier */
+	case '%': {
+	    char *endp;
+	    long conv_len1=0, conv_len2=0, conv_len=0;
+	    signed int arg_size;
+
+	    /* Firstly, strip the modifier flags (+-#0 and [space]) */
+	    for(; c=*++cp;) {
+		if ('#' == c)
+		    len+=2; /* Worst case of "0x" */
+		else if ('-' == c || '+' == c || ' ' == c)
+		    len++;
+		else
+		    break;
+	    }
+
+	    /* Width specifier */
+	    l = strtol(cp, &endp, 10);
+	    if (endp != cp) {
+		cp = endp;
+		conv_len = conv_len1 = l;
+	    } else if (*cp == '*') {
+		conv_len = conv_len1 = (int)va_arg(ap, int);
+		cp++;
+	    }
+
+	    /* Precision specifier */
+	    if ('.' == *cp) {
+		cp++;
+		conv_len2 = strtol(cp, &endp, 10);
+		if (endp != cp) {
+		    cp = endp;
+		} else if (*cp == '*') {
+		    conv_len2 = (int)va_arg(ap, int);
+		    cp++;
+		}
+		conv_len = MAX(conv_len1, conv_len2);
+	    }
+
+	    /* Short/long identifier */
+	    if ('h' == *cp) {
+		arg_size = -1; /* short */
+		cp++;
+	    } else if ('l' == *cp) {
+		arg_size = 1; /* long */
+		cp++;
+	    } else {
+		arg_size = 0; /* int */
+	    }
+
+	    /* The actual type */
+	    switch (*cp) {
+	    case '%':
+		/*
+		 * Not real ANSI I suspect, but we'll allow for the
+		 * completely daft "%10%" example.
+		 */
+		len += MAX(conv_len1, 1);
+		break;
+
+	    case 'd':
+	    case 'i':
+	    case 'u':
+	    case 'a':
+	    case 'x':
+	    case 'X':
+		/* Remember: char and short are sent as int on the stack */
+		if (arg_size == -1)
+		    l = (long)va_arg(ap, int);
+		else if (arg_size == 1)
+		    l = va_arg(ap, long); 
+		else 
+		    l = (long)va_arg(ap, int);
+
+		DEBUG_printf("%d", l);
+
+		/*
+		 * No number can be more than 24 characters so we'll take
+		 * the max of conv_len and 24 (23 is len(2^64) in octal).
+		 * All that work above and we then go and estimate ;-),
+		 * but it's needed incase someone does %500d.
+		 */
+		len += MAX(conv_len, 23);
+		break;
+
+	    case 'c':
+		i = va_arg(ap, int);
+		DEBUG_printf("%c", i);
+		/*
+		 * Note that %10c and %.10c act differently.
+		 * Besides, I think precision is not really allowed for %c.
+		 */
+		len += MAX(conv_len1, 1);
+		break;
+
+	    case 'f':
+		d = va_arg(ap, double);
+		DEBUG_printf("%f", d);
+		/*
+		 * Maybe "Inf" or "NaN", but we'll not worry about that.
+		 * Again, err on side of caution and take max of conv_len
+		 * and max length of a double. The worst case I can
+		 * think of is 317 characters (-1[308 zeros].000000)
+		 * without using precision codes. That's horrid. I
+		 * cheat and either use 317 or 15 depending on how
+		 * large the number is as I reckon 99% of floats
+		 * aren't that long.
+		 */
+		l = (ABS(d) > 1000000) ? 317 : 15;
+		l = MAX(l, conv_len1 + 2);
+		if (conv_len2) l += conv_len2 - 6;
+		len += l;
+		break;
+
+	    case 'e':
+	    case 'E':
+	    case 'g':
+	    case 'G':
+		d = va_arg(ap, double);
+		DEBUG_printf("%g", d);
+		/*
+		 * Maybe "Inf" or "NaN", but we'll not worry about that
+		 * Again, err on side of caution and take max of conv_len
+		 * and max length of a double (which defaults to only
+		 * '-' + 6 + '.' + 'E[+-]xxx' == 13.
+		 */
+		len += MAX(conv_len, 13);
+		break;
+
+	    case 'p':
+		l = (long)va_arg(ap, void *);
+		/*
+		 * Max pointer is 64bits == 16 chars (on alpha),
+		 * == 20 with + "0x".
+		 */
+		DEBUG_printf("%p", (void *)l);
+		len += MAX(conv_len, 20);
+		break;
+
+	    case 'n':
+		/* produces no output */
+		break;
+
+	    case 's': {
+		char *s = (char *)va_arg(ap, char *);
+		DEBUG_printf("%s", s);
+
+		if (!conv_len2) {
+		    len += MAX(conv_len, (int)strlen(s));
+		} else {
+		    len += conv_len;
+		}
+		break;
+	    }
+
+	    default:
+		/* wchar_t types of 'C' and 'S' aren't supported */
+		DEBUG_printf("Arg is %c\n", *cp);
+	    }
+	    
+	}
+
+	case '\0':
+	    break;
+
+	default:
+	    DEBUG_printf("%c", *cp);
+	    len++;
+	}
+    }
+
+    va_end(ap);
+
+    return len+1; /* one for the null character */
+}
+
+#if 0
+int main() {
+    int l;
+    char buf[10000];
+
+    sprintf(buf, "d: %d\n", 500);
+    l = flen("d: %d\n", 500);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "");
+    l = flen("");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%s\n","test");
+    l = flen("%s\n", "test");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%c\n", 'a');
+    l = flen("%c\n", 'a');
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%31.30f\n", -9999.99);
+    l = flen("%31.30f\n", -9999.99);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%f\n", -1e308);
+    l = flen("%f\n", -1e308);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%.9f\n", -1e308);
+    l = flen("%.9f\n", -1e308);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%10.20f\n", -1.999222333);
+    l = flen("%10.20f\n", -1.999222333);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%#g\n", -3.14159265358e-222);
+    l = flen("%#g\n", -3.1415927e-222);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%e\n", -123456789123456789.1);
+    l = flen("%e\n", -123456789123456789.1);
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%c %f %d %s %c %g %ld %s\n", 'a', 3.1, 9, "one", 'b', 4.2, 9, "two");
+    l = flen("%c %f %d %s %c %g %ld %s\n", 'a', 3.1, 9, "one", 'b', 4.2, 9, "two");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%*.*e %*c\n", 10, 5, 9.0, 20, 'x');
+    l = flen("%*.*e %*c\n", 10, 5, 9.0, 20, 'x');
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%10c\n", 'z');
+    l = flen("%10c\n", 'z');
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%.10c\n", 'z');
+    l = flen("%.10c\n", 'z');
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%10d\n", 'z');
+    l = flen("%10d\n", 'z');
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%.10d\n", 'z');
+    l = flen("%.10d\n", 'z');
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%10%\n");
+    l = flen("%10%\n");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%.10%\n");
+    l = flen("%.10%\n");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%s\n", "0123456789");
+    l = flen("%s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%5s\n", "0123456789");
+    l = flen("%5s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%50s\n", "0123456789");
+    l = flen("%50s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%.5s\n", "0123456789");
+    l = flen("%.5s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%.50s\n", "0123456789");
+    l = flen("%.50s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%5.50s\n", "0123456789");
+    l = flen("%5.50s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    sprintf(buf, "%50.5s\n", "0123456789");
+    l = flen("%50.5s\n", "0123456789");
+    printf("%d %d\n\n", strlen(buf), l);
+
+    return 0;
+}
+#endif