Revision: 49046 http://brlcad.svn.sourceforge.net/brlcad/?rev=49046&view=rev Author: n_reed Date: 2012-01-24 20:25:17 +0000 (Tue, 24 Jan 2012) Log Message: ----------- Removed use of vsscanf and re-wrote test to be simpler, more readable, and more portable.
Modified Paths: -------------- brlcad/trunk/src/libbu/test_sscanf.c Modified: brlcad/trunk/src/libbu/test_sscanf.c =================================================================== --- brlcad/trunk/src/libbu/test_sscanf.c 2012-01-24 20:22:18 UTC (rev 49045) +++ brlcad/trunk/src/libbu/test_sscanf.c 2012-01-24 20:25:17 UTC (rev 49046) @@ -29,7 +29,6 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> -#include <limits.h> #include <float.h> #include "bu.h" @@ -102,204 +101,172 @@ * pointer. PROBABLY shouldn't affect returned conversion count. */ -/* Macro for creating type-specific test routines. - * - * conv_spec - * lf, d, c, ... creates test_sscanf_lf, test_sscanf_d, ... - * val_type - * double, int, char, ... - * val_test - * equality test for two val_type vals named a and b, like (a == b) - */ -#ifdef HAVE_VSSCANF -#define TEST_SSCANF(conv_spec, val_type, val_test) \ -/* returns true if a and b are equal */ \ -static int \ -equal_##conv_spec(val_type a, val_type b) { \ - return val_test; \ -} \ -/* Runs vsscanf and bu_vsscanf, compares their return values and, - * if they match, compares their conversion values. On any mismatch, - * prints log and returns. - */ \ -static void \ -test_sscanf_##conv_spec(const char *src, const char *fmt, ...) \ -{ \ - va_list ap; \ - int i, ret, bu_ret; \ - val_type *values = NULL; \ - val_type *bu_values = NULL; \ - /* run system routine */ \ - va_start(ap, fmt); \ - ret = vsscanf(src, fmt, ap); \ - va_end(ap); \ - if (ret > 0) { \ - /* Create value arrays. Return tells us how many values we converted, \ - * which will be less than or (hopefully) equal to the number of \ - * pointers in the va_list. \ - */ \ - values = (val_type*)bu_malloc(ret * sizeof(val_type), "test_sscanf: value array"); \ - bu_values = (val_type*)bu_malloc(ret * sizeof(val_type), "test_sscanf: bu_value array"); \ - /* copy vsscanf pointer values to array */ \ - va_start(ap, fmt); \ - for (i = 0; i < ret; ++i) { \ - values[i] = *va_arg(ap, val_type*); \ - } \ - va_end(ap); \ - } else { \ - printf("Warning: no assignments done for %s.\n", fmt); \ - } \ - /* run bu routine */ \ - va_start(ap, fmt); \ - bu_ret = bu_vsscanf(src, fmt, ap); \ - va_end(ap); \ - /* return values equal? */ \ - if (bu_ret != ret) { \ - printf("[FAIL] sscanf returned %d but bu_sscanf returned %d\n", \ - ret, bu_ret); \ - return; \ - } \ - /* conversion values equal? */ \ - if (values != NULL && bu_values != NULL) { \ - /* copy bu_vsscanf pointer values to array */ \ - va_start(ap, fmt); \ - for (i = 0; i < bu_ret; ++i) { \ - bu_values[i] = *va_arg(ap, val_type*); \ - } \ - va_end(ap); \ - /* compare vsscanf and bu_vsscanf values */ \ - for (i = 0; i < ret; ++i) { \ - if (!equal_##conv_spec(values[i], bu_values[i])) { \ - printf("[FAIL] conversion value mismatch. " \ - "(sscanf) %" #conv_spec "!= %" #conv_spec " (bu_sscanf)\n", \ - values[i], bu_values[i]); \ - break; \ - } \ - } \ - bu_free(values, "test_sscanf: value array\n"); \ - values = NULL; \ - bu_free(bu_values, "test_sscanf: bu_value array\n"); \ - bu_values = NULL; \ - } \ -} -#else -#define TEST_SSCANF(conv_spec, val_type, val_test) /* nop */ -#endif +enum { + INT, UINT, SHORT, USHORT, LONG, ULONG, + FLOAT, DOUBLE, LDOUBLE +}; -/* string test routine */ -#ifdef HAVE_VSSCANF static void -test_sscanf_s(const char *src, const char *fmt, ...) -{ - va_list ap; - int i, ret, bu_ret; - char **values = NULL; - char **bu_values = NULL; +test_sscanf(int type, const char *src, const char *fmt) { + int ret, bu_ret; + void *val, *bu_val; - /* run system routine */ - va_start(ap, fmt); - ret = vsscanf(src, fmt, ap); - va_end(ap); + val = bu_val = NULL; - if (ret > 0) { - /* Create string arrays. Copy vsscanf pointer values to array. */ - values = (char**)bu_malloc(ret * sizeof(char*), "test_sscanf: value array"); - bu_values = (char**)bu_malloc(ret * sizeof(char*), "test_sscanf: value array"); + printf("(%s, %s)\n", src, fmt); - va_start(ap, fmt); - for (i = 0; i < ret; ++i) { - values[i] = (char*)bu_malloc(STR_SIZE * sizeof(char), - "test_sscanf: value array"); + /* call sscanf and bu_sscanf with appropriately cast pointers */ +#define SSCANF_TYPE(type) \ + val = bu_malloc(sizeof(type), "test_sscanf val"); \ + bu_val = bu_malloc(sizeof(type), "test_sscanf bu_val"); \ + ret = sscanf(src, fmt, (type*)val); \ + bu_ret = bu_sscanf(src, fmt, (type*)bu_val); - bu_values[i] = (char*)bu_malloc(STR_SIZE * sizeof(char), - "test_sscanf: bu_value array"); + switch (type) { + case INT: + SSCANF_TYPE(int); + break; + case UINT: + SSCANF_TYPE(unsigned); + break; + case SHORT: + SSCANF_TYPE(short); + break; + case USHORT: + SSCANF_TYPE(unsigned short); + break; + case LONG: + SSCANF_TYPE(long); + break; + case ULONG: + SSCANF_TYPE(unsigned long); + break; + case FLOAT: + SSCANF_TYPE(float); + break; + case DOUBLE: + SSCANF_TYPE(double); + break; + case LDOUBLE: + SSCANF_TYPE(long double); + break; + } - strcpy(values[i], va_arg(ap, char*)); - } - va_end(ap); - } else { - printf("Warning: no assignments done for %s.\n", fmt); + if (ret != 1) { + printf("\tWarning: no assignment done.\n"); } - /* run bu routine */ - va_start(ap, fmt); - bu_ret = bu_vsscanf(src, fmt, ap); - va_end(ap); /* return values equal? */ if (bu_ret != ret) { - printf("[FAIL] sscanf returned %d but bu_sscanf returned %d\n", + printf("\t[FAIL] sscanf returned %d but bu_sscanf returned %d.\n", ret, bu_ret); - printf("\tSource was \"%s\"\n", src); - printf("\tFormat was \"%s\"\n", fmt); return; } + +#define CHECK_INT(type, conv_spec) \ + if (*(type*)val != *(type*)bu_val) { \ + printf("\t[FAIL] conversion value mismatch.\n" \ + "\t(sscanf) %" # conv_spec " != %" # conv_spec " (bu_sscanf).\n", \ + *(type*)val, *(type*)bu_val); \ + } + +#define CHECK_FLOAT(type, conv_spec) \ + if (!NEAR_EQUAL(*(type*)val, *(type*)bu_val, FLOAT_TOL)) { \ + printf("\t[FAIL] conversion value mismatch.\n" \ + "\t(sscanf) %" # conv_spec " != %" # conv_spec " (bu_sscanf).\n", \ + *(type*)val, *(type*)bu_val); \ + } + /* conversion values equal? */ - if (values != NULL && bu_values != NULL) { + if (val != NULL && bu_val != NULL) { - /* copy bu_vsscanf pointer values to array */ - va_start(ap, fmt); - for (i = 0; i < bu_ret; ++i) { - strcpy(bu_values[i], va_arg(ap, char*)); + switch (type) { + case INT: + CHECK_INT(int, d); + break; + case UINT: + CHECK_INT(unsigned, u); + break; + case SHORT: + CHECK_INT(short, hd); + break; + case USHORT: + CHECK_INT(unsigned short, hu); + break; + case LONG: + CHECK_INT(long, ld); + break; + case ULONG: + CHECK_INT(unsigned long, lu); + break; + case FLOAT: + CHECK_FLOAT(float, e); + break; + case DOUBLE: + CHECK_FLOAT(double, le); + break; + case LDOUBLE: + CHECK_FLOAT(long double, Le); + break; } - va_end(ap); + bu_free(val, "test_sscanf val"); + val = NULL; + bu_free(bu_val, "test_sscanf bu_val"); + bu_val = NULL; + } +} /* test_sscanf */ - /* compare vsscanf and bu_vsscanf values */ - for (i = 0; i < ret; ++i) { - if (!BU_STR_EQUAL(values[i], bu_values[i])) { - printf("[FAIL] conversion value mismatch. " - "(sscanf) %s != %s (bu_sscanf)\n", - values[i], bu_values[i]); - printf("\tSource was \"%s\"\n", src); - printf("\tFormat was \"%s\"\n", fmt); - break; - } - } - bu_free_array(ret, values, "test_sscanf: values\n"); - bu_free_array(ret, bu_values, "test_sscanf: bu_values\n"); - bu_free(values, "test_sscanf: value array\n"); - bu_free(bu_values, "test_sscanf: bu_value array\n"); - values = bu_values = NULL; +/* string test routine */ +static void +test_sscanf_s(const char *src, const char *fmt) +{ + int ret, bu_ret; + char dest[STR_SIZE], bu_dest[STR_SIZE]; + + printf("(%s, %s)\n", src, fmt); + + ret = sscanf(src, fmt, dest); + bu_ret = bu_sscanf(src, fmt, bu_dest); + + if (ret != 1) { + printf("\tWarning: no assignments done.\n"); } + + /* return values equal? */ + if (bu_ret != ret) { + printf("\t[FAIL] sscanf returned %d but bu_sscanf returned %d.\n", + ret, bu_ret); + return; + } + + /* conversion values equal? */ + if (!BU_STR_EQUAL(dest, bu_dest)) { + printf("\t[FAIL] conversion value mismatch.\n" + "\t(sscanf) %s != %s (bu_sscanf).\n", + dest, bu_dest); + } } -#else -#define test_sscanf_s sscanf -#endif -/* integer test routines */ -TEST_SSCANF(d, int, (a == b)) -TEST_SSCANF(hd, short int, (a == b)) -TEST_SSCANF(ld, long int, (a == b)) -TEST_SSCANF(u, unsigned int, (a == b)) -TEST_SSCANF(hu, unsigned short int, (a == b)) -TEST_SSCANF(lu, unsigned long int, (a == b)) -TEST_SSCANF(c, char, (a == b)) -/* floating-point test routines */ -TEST_SSCANF(f, float, (NEAR_EQUAL(a, b, FLOAT_TOL))) -TEST_SSCANF(lf, double, (NEAR_EQUAL(a, b, FLOAT_TOL))) -TEST_SSCANF(Lf, long double, (NEAR_EQUAL(a, b, FLOAT_TOL))) +/* The problem with the macros in limits.h is that they aren't necessarily + * printable. We could have something like: + * #define INT_MIN (-INT_MAX - 1) + * + * So, here we define printable constants that should be safe on any + * platform. + */ +#define SMALL_INT -32767 /* -2^15 + 1 (not assuming 2's complement) */ +#define LARGE_INT +32767 /* 2^15 - 1 */ +#define LARGE_UINT 65535 /* 2^16 - 1 */ +#define SMALL_LONG -2147483647L /* -2^31 + 1 */ +#define LARGE_LONG +2147483647L /* 2^31 - 1 */ +#define LARGE_ULONG 4294967295U /* 2^32 - 1 */ + int main(int argc, char *argv[]) { - int d_vals[3]; - short hd_vals[3]; - long ld_vals[3]; - unsigned u_vals[2]; - unsigned short hu_vals[2]; - unsigned long lu_vals[2]; - float f_vals[6]; - double lf_vals[6]; - long double Lf_vals[6]; - char c_vals[3]; - char s_vals[3][STR_SIZE]; - -#ifndef HAVE_VSSCANF - printf("%s requires a system vsscanf for proper execution.\n", argv[0]); - return 0; -#endif - if (argc > 1) { printf("Warning: %s takes no arguments.\n", argv[0]); } @@ -322,41 +289,44 @@ */ /* signed integer tests */ - test_sscanf_d("0 +" bu_cpp_xstr(INT_MAX) " -" bu_cpp_xstr(INT_MIN), - "%d %d %d", &d_vals[0], &d_vals[1], &d_vals[2]); - test_sscanf_hd("0 +" bu_cpp_xstr(SHRT_MAX) " -" bu_cpp_xstr(SHRT_MIN), - "%hd %hd %hd", &hd_vals[0], &hd_vals[1], &hd_vals[2]); - test_sscanf_ld("0 +" bu_cpp_xstr(LONG_MAX) " -" bu_cpp_xstr(LONG_MIN), - "%ld %ld %ld", &ld_vals[0], &ld_vals[1], &ld_vals[2]); + test_sscanf(INT, "0", "%d"); + test_sscanf(INT, bu_cpp_xstr(LARGE_INT), "%d"); + test_sscanf(INT, bu_cpp_xstr(SMALL_INT), "%d"); + test_sscanf(SHORT, "0", "%hd"); + test_sscanf(SHORT, bu_cpp_xstr(LARGE_INT), "%hd"); + test_sscanf(SHORT, bu_cpp_xstr(SMALL_INT), "%hd"); + + test_sscanf(LONG, "0", "%ld"); + test_sscanf(LONG, bu_cpp_xstr(LARGE_LONG), "%ld"); + test_sscanf(LONG, bu_cpp_xstr(SMALL_LONG), "%ld"); + /* unsigned integer tests */ - test_sscanf_u("0 " bu_cpp_xstr(UINT_MAX), "%u %u", &u_vals[0], &u_vals[1]); - test_sscanf_hu("0 " bu_cpp_xstr(USHRT_MAX), "%hu %hu", &hu_vals[0], &hu_vals[1]); - test_sscanf_lu("0 " bu_cpp_xstr(ULONG_MAX), "%lu %lu", &lu_vals[0], &lu_vals[1]); + test_sscanf(UINT, "0", "%u"); + test_sscanf(UINT, bu_cpp_xstr(LARGE_UINT), "%u"); - test_sscanf_lu("0 " bu_cpp_xstr(ULONG_MAX), "%lu %lu", &lu_vals[0], &lu_vals[1]); + test_sscanf(USHORT, "0", "%hu"); + test_sscanf(USHORT, bu_cpp_xstr(LARGE_UINT), "%hu"); + test_sscanf(ULONG, "0", "%lu"); + test_sscanf(ULONG, bu_cpp_xstr(LARGE_ULONG), "%lu"); + /* float tests */ - test_sscanf_f("0.0 .0123 .4567 8.91011 " bu_cpp_xstr(FLT_MIN) " " - bu_cpp_xstr(FLT_MAX), "%f %f %f %f %f %f", &f_vals[0], &f_vals[1], - &f_vals[2], &f_vals[3], &f_vals[4], &f_vals[5]); + test_sscanf(FLOAT, "0.0F", "%f"); + test_sscanf(FLOAT, bu_cpp_xstr(FLT_MAX), "%f"); + test_sscanf(FLOAT, bu_cpp_xstr(FLT_MIN), "%f"); - test_sscanf_lf("0.0 .0123 .4567 8.91011 " bu_cpp_xstr(DBL_MIN) " " - bu_cpp_xstr(DBL_MAX), "%lf %lf %lf %lf %lf %lf", &lf_vals[0], - &lf_vals[1], &lf_vals[2], &lf_vals[3], &lf_vals[4], &lf_vals[5]); + test_sscanf(DOUBLE, "0.0", "%lf"); + test_sscanf(DOUBLE, bu_cpp_xstr(DBL_MAX), "%lf"); + test_sscanf(DOUBLE, bu_cpp_xstr(DBL_MIN), "%lf"); - test_sscanf_Lf("0.0 .0123 .4567 8.91011 " bu_cpp_xstr(LDBL_MIN) " " - bu_cpp_xstr(LDBL_MAX), "%Lf %Lf %Lf %Lf %Lf %Lf", &Lf_vals[0], - &Lf_vals[1], &Lf_vals[2], &Lf_vals[3], &Lf_vals[4], &Lf_vals[5]); + test_sscanf(LDOUBLE, "0.0L", "%Lf"); + test_sscanf(LDOUBLE, bu_cpp_xstr(LDBL_MAX), "%Lf"); + test_sscanf(LDOUBLE, bu_cpp_xstr(LDBL_MIN), "%Lf"); /* string tests */ - test_sscanf_s(" aBc DeF gHi\t", "%s %s %s", - s_vals[0], s_vals[1], s_vals[2]); + test_sscanf_s(" aBc \t", "%s"); - test_sscanf_c("a b c", "%c %c %c", - &c_vals[0], &c_vals[1], &c_vals[2]); - - printf("bu_sscanf: testing complete\n"); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Keep Your Developer Skills Current with LearnDevNow! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-d2d _______________________________________________ BRL-CAD Source Commits mailing list brlcad-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/brlcad-commits