[gcalctool] Test for conversions



commit 1c0413fd1275609a2bdfc3cc4ace940e8bf68726
Author: Robert Ancell <robert ancell gmail com>
Date:   Thu Mar 18 22:19:48 2010 +1100

    Test for conversions

 src/display.c             |  158 +------------------------------------------
 src/mp-equation-parser.y  |    6 +--
 src/mp-equation-private.h |    3 +
 src/mp-equation.c         |  165 +++++++++++++++++++++++++++++++++++++++++++++
 src/unittest.c            |   33 ++++++++-
 5 files changed, 201 insertions(+), 164 deletions(-)
---
diff --git a/src/display.c b/src/display.c
index 07565fd..6f5054f 100644
--- a/src/display.c
+++ b/src/display.c
@@ -807,156 +807,9 @@ set_variable(const char *name, const MPNumber *x, void *data)
 
 
 static int
-do_convert(const char *units[][2], const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
-{
-    int x_index, z_index;
-    MPNumber x_factor, z_factor;
-    
-    for (x_index = 0; units[x_index][0] != NULL && strcmp(units[x_index][0], x_units) != 0; x_index++);
-    if (units[x_index][0] == NULL)
-        return 0;
-    for (z_index = 0; units[z_index][0] != NULL && strcmp(units[z_index][0], z_units) != 0; z_index++);
-    if (units[z_index][0] == NULL)
-        return 0;
-
-    mp_set_from_string(units[x_index][1], &x_factor);
-    mp_set_from_string(units[z_index][1], &z_factor);
-    mp_multiply(x, &x_factor, z);
-    mp_divide(z, &z_factor, z);
-
-    return 1;
-}
-
-
-static int
 convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z, void *data)
-{
-    const char *length_units[][2] = {
-        {"parsec",     "30857000000000000"},
-        {"parsecs",    "30857000000000000"},
-        {"pc",         "30857000000000000"},
-        {"lightyear",   "9460730472580800"},
-        {"lightyears",  "9460730472580800"},
-        {"ly",          "9460730472580800"},
-        {"au",              "149597870691"},
-        {"nm",                   "1852000"},
-        {"mile",                    "1609.344"},
-        {"miles",                   "1609.344"},
-        {"mi",                      "1609.344"},
-        {"kilometer",               "1000"},
-        {"kilometers",              "1000"},
-        {"km",                      "1000"},
-        {"kms",                     "1000"},
-        {"cable",                    "219.456"},
-        {"cables",                   "219.456"},
-        {"cb",                       "219.456"},
-        {"fathom",                     "1.8288"},
-        {"fathoms",                    "1.8288"},
-        {"ftm",                        "1.8288"},
-        {"meter",                      "1"},
-        {"meters",                     "1"},
-        {"m",                          "1"},
-        {"yard",                       "0.9144"},
-        {"yd",                         "0.9144"},
-        {"foot",                       "0.3048"},
-        {"feet",                       "0.3048"},
-        {"ft",                         "0.3048"},
-        {"inch",                       "0.0254"},
-        {"inches",                     "0.0254"},
-        {"centimeter",                 "0.01"},
-        {"centimeters",                "0.01"},
-        {"cm",                         "0.01"},
-        {"cms",                        "0.01"},
-        {"millimeter",                 "0.001"},
-        {"millimeters",                "0.001"},
-        {"mm",                         "0.001"},
-        {"micrometer",                 "0.000001"},
-        {"micrometers",                "0.000001"},
-        {"um",                         "0.000001"},
-        {"nanometer",                  "0.000000001"},
-        {"nanometers",                 "0.000000001"},
-        {NULL, NULL}
-    };
-
-    const char *area_units[][2] = {
-        {"hectare",         "10000"},
-        {"hectares",        "10000"},
-        {"acre",             "4046.8564224"},
-        {"acres",            "4046.8564224"},
-        {"m²",                  "1"},
-        {"cm²",                 "0.001"},
-        {NULL, NULL}
-    };
-
-    const char *volume_units[][2] = {
-        {"cm³",              "1000"},
-        {"gallon",              "3.785412"},
-        {"gallons",             "3.785412"},
-        {"gal",                 "3.785412"},
-        {"litre",               "1"},
-        {"litres",              "1"},
-        {"liter",               "1"},
-        {"liters",              "1"},
-        {"L",                   "1"},
-        {"quart",               "0.9463529"},
-        {"quarts",              "0.9463529"},
-        {"qt",                  "0.9463529"},
-        {"pint",                "0.4731765"},
-        {"pints",               "0.4731765"},
-        {"pt",                  "0.4731765"},
-        {"millilitre",          "0.001"},
-        {"millilitres",         "0.001"},
-        {"milliliter",          "0.001"},
-        {"milliliters",         "0.001"},
-        {"mL",                  "0.001"},
-        {"m³",                  "0.001"},
-        {NULL, NULL}
-    };
-
-    const char *weight_units[][2] = {
-        {"tonne",            "1000"},
-        {"tonnes",           "1000"},
-        {"kilograms",           "1"},
-        {"kilogramme",          "1"},
-        {"kilogrammes",         "1"},
-        {"kg",                  "1"},
-        {"kgs",                 "1"},
-        {"pound",               "0.45359237"},
-        {"pounds",              "0.45359237"},
-        {"lb",                  "0.45359237"},
-        {"ounce",               "0.002834952"},
-        {"ounces",              "0.002834952"},
-        {"oz",                  "0.002834952"},
-        {"gram",                "0.001"},
-        {"grams",               "0.001"},
-        {"gramme",              "0.001"},
-        {"grammes",             "0.001"},
-        {"g",                   "0.001"},
-        {NULL, NULL}
-    };
-    
-    const char *time_units[][2] = {
-        {"year",         "31557600"},
-        {"years",        "31557600"},
-        {"day",             "86400"},
-        {"days",            "86400"},
-        {"hour",             "3600"},
-        {"hours",            "3600"},
-        {"minute",             "60"},
-        {"minutes",            "60"},
-        {"second",              "1"},
-        {"seconds",             "1"},
-        {"s",                   "1"},
-        {"millisecond",         "0.001"},
-        {"milliseconds",        "0.001"},
-        {"ms",                  "0.001"},
-        {"microsecond",         "0.000001"},
-        {"microseconds",        "0.000001"},
-        {"us",                  "0.000001"},
-        {NULL, NULL}
-    };
-    
-    /* See if currency */
+{   
+    /* Update currency if necessary */
     if (currency_rates_needs_update())
         currency_download_rates();
     currency_load_rates();
@@ -965,13 +818,6 @@ convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z
         currency_convert(x, currency_get_index(x_units), currency_get_index(z_units), z);
         return 1;
     }
-    
-    if (do_convert(length_units, x, x_units, z_units, z) ||
-        do_convert(area_units, x, x_units, z_units, z) ||
-        do_convert(volume_units, x, x_units, z_units, z) ||
-        do_convert(weight_units, x, x_units, z_units, z) ||
-        do_convert(time_units, x, x_units, z_units, z))
-        return 1;
 
     return 0;
 }
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index a882695..440741c 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -124,12 +124,8 @@ static void do_not(yyscan_t yyscanner, const MPNumber *x, MPNumber *z)
 
 static void do_conversion(yyscan_t yyscanner, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
 {
-    void *data = _mp_equation_get_extra(yyscanner)->options->callback_data;
-
-    if (_mp_equation_get_extra(yyscanner)->options->convert == NULL
-        || !_mp_equation_get_extra(yyscanner)->options->convert(x, x_units, z_units, z, data)) {
+    if (!_mp_equation_get_extra(yyscanner)->convert(_mp_equation_get_extra(yyscanner), x, x_units, z_units, z))
         set_error(yyscanner, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
-    }
 }
 
 %}
diff --git a/src/mp-equation-private.h b/src/mp-equation-private.h
index 190c71a..7ef96c2 100644
--- a/src/mp-equation-private.h
+++ b/src/mp-equation-private.h
@@ -44,6 +44,9 @@ struct MPEquationParserState {
     /* Function to solve functions */
     int (*get_function)(MPEquationParserState *state, const char *name, const MPNumber *x, MPNumber *z);
 
+    /* Function to convert units */
+    int (*convert)(MPEquationParserState *state, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z);
+
     // FIXME: get_operator??
 
     /* Error returned from parser */
diff --git a/src/mp-equation.c b/src/mp-equation.c
index 180fff1..e13f20b 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -222,6 +222,170 @@ get_function(MPEquationParserState *state, const char *name, const MPNumber *x,
 }
 
 
+static int
+do_convert(const char *units[][2], const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
+{
+    int x_index, z_index;
+    MPNumber x_factor, z_factor;
+    
+    for (x_index = 0; units[x_index][0] != NULL && strcmp(units[x_index][0], x_units) != 0; x_index++);
+    if (units[x_index][0] == NULL)
+        return 0;
+    for (z_index = 0; units[z_index][0] != NULL && strcmp(units[z_index][0], z_units) != 0; z_index++);
+    if (units[z_index][0] == NULL)
+        return 0;
+
+    mp_set_from_string(units[x_index][1], &x_factor);
+    mp_set_from_string(units[z_index][1], &z_factor);
+    mp_multiply(x, &x_factor, z);
+    mp_divide(z, &z_factor, z);
+
+    return 1;
+}
+
+
+static int
+convert(MPEquationParserState *state, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
+{
+    const char *length_units[][2] = {
+        {"parsec",     "30857000000000000"},
+        {"parsecs",    "30857000000000000"},
+        {"pc",         "30857000000000000"},
+        {"lightyear",   "9460730472580800"},
+        {"lightyears",  "9460730472580800"},
+        {"ly",          "9460730472580800"},
+        {"au",              "149597870691"},
+        {"nm",                   "1852000"},
+        {"mile",                    "1609.344"},
+        {"miles",                   "1609.344"},
+        {"mi",                      "1609.344"},
+        {"kilometer",               "1000"},
+        {"kilometers",              "1000"},
+        {"km",                      "1000"},
+        {"kms",                     "1000"},
+        {"cable",                    "219.456"},
+        {"cables",                   "219.456"},
+        {"cb",                       "219.456"},
+        {"fathom",                     "1.8288"},
+        {"fathoms",                    "1.8288"},
+        {"ftm",                        "1.8288"},
+        {"meter",                      "1"},
+        {"meters",                     "1"},
+        {"m",                          "1"},
+        {"yard",                       "0.9144"},
+        {"yd",                         "0.9144"},
+        {"foot",                       "0.3048"},
+        {"feet",                       "0.3048"},
+        {"ft",                         "0.3048"},
+        {"inch",                       "0.0254"},
+        {"inches",                     "0.0254"},
+        {"centimeter",                 "0.01"},
+        {"centimeters",                "0.01"},
+        {"cm",                         "0.01"},
+        {"cms",                        "0.01"},
+        {"millimeter",                 "0.001"},
+        {"millimeters",                "0.001"},
+        {"mm",                         "0.001"},
+        {"micrometer",                 "0.000001"},
+        {"micrometers",                "0.000001"},
+        {"um",                         "0.000001"},
+        {"nanometer",                  "0.000000001"},
+        {"nanometers",                 "0.000000001"},
+        {NULL, NULL}
+    };
+
+    const char *area_units[][2] = {
+        {"hectare",         "10000"},
+        {"hectares",        "10000"},
+        {"acre",             "4046.8564224"},
+        {"acres",            "4046.8564224"},
+        {"m²",                  "1"},
+        {"cm²",                 "0.001"},
+        {NULL, NULL}
+    };
+
+    const char *volume_units[][2] = {
+        {"cm³",              "1000"},
+        {"gallon",              "3.785412"},
+        {"gallons",             "3.785412"},
+        {"gal",                 "3.785412"},
+        {"litre",               "1"},
+        {"litres",              "1"},
+        {"liter",               "1"},
+        {"liters",              "1"},
+        {"L",                   "1"},
+        {"quart",               "0.9463529"},
+        {"quarts",              "0.9463529"},
+        {"qt",                  "0.9463529"},
+        {"pint",                "0.4731765"},
+        {"pints",               "0.4731765"},
+        {"pt",                  "0.4731765"},
+        {"millilitre",          "0.001"},
+        {"millilitres",         "0.001"},
+        {"milliliter",          "0.001"},
+        {"milliliters",         "0.001"},
+        {"mL",                  "0.001"},
+        {"m³",                  "0.001"},
+        {NULL, NULL}
+    };
+
+    const char *weight_units[][2] = {
+        {"tonne",            "1000"},
+        {"tonnes",           "1000"},
+        {"kilograms",           "1"},
+        {"kilogramme",          "1"},
+        {"kilogrammes",         "1"},
+        {"kg",                  "1"},
+        {"kgs",                 "1"},
+        {"pound",               "0.45359237"},
+        {"pounds",              "0.45359237"},
+        {"lb",                  "0.45359237"},
+        {"ounce",               "0.002834952"},
+        {"ounces",              "0.002834952"},
+        {"oz",                  "0.002834952"},
+        {"gram",                "0.001"},
+        {"grams",               "0.001"},
+        {"gramme",              "0.001"},
+        {"grammes",             "0.001"},
+        {"g",                   "0.001"},
+        {NULL, NULL}
+    };
+    
+    const char *time_units[][2] = {
+        {"year",         "31557600"},
+        {"years",        "31557600"},
+        {"day",             "86400"},
+        {"days",            "86400"},
+        {"hour",             "3600"},
+        {"hours",            "3600"},
+        {"minute",             "60"},
+        {"minutes",            "60"},
+        {"second",              "1"},
+        {"seconds",             "1"},
+        {"s",                   "1"},
+        {"millisecond",         "0.001"},
+        {"milliseconds",        "0.001"},
+        {"ms",                  "0.001"},
+        {"microsecond",         "0.000001"},
+        {"microseconds",        "0.000001"},
+        {"us",                  "0.000001"},
+        {NULL, NULL}
+    };
+
+    if (do_convert(length_units, x, x_units, z_units, z) ||
+        do_convert(area_units, x, x_units, z_units, z) ||
+        do_convert(volume_units, x, x_units, z_units, z) ||
+        do_convert(weight_units, x, x_units, z_units, z) ||
+        do_convert(time_units, x, x_units, z_units, z))
+        return 1;
+
+    if (state->options->convert)
+        return state->options->convert(x, x_units, z_units, z, state->options->callback_data);
+  
+    return 0;
+}
+
+
 MPErrorCode
 mp_equation_parse(const char *expression, MPEquationOptions *options, MPNumber *result, char **error_token)
 {
@@ -240,6 +404,7 @@ mp_equation_parse(const char *expression, MPEquationOptions *options, MPNumber *
     state.set_variable = set_variable;
     state.function_is_defined = function_is_defined;
     state.get_function = get_function;
+    state.convert = convert;
     state.error = 0;
 
     mp_clear_error();
diff --git a/src/unittest.c b/src/unittest.c
index e3eb2a6..defb1ab 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -102,6 +102,33 @@ test(char *expression, char *expected, int expected_error)
 }
 
 
+static void
+test_conversions()
+{
+    memset(&options, 0, sizeof(options));
+    base = 10;
+    options.wordlen = 32;
+    options.angle_units = MP_DEGREES;
+
+    /* Length */
+    test("1 meter in mm", "1000", 0);  
+    test("1m in mm", "1000", 0);
+    test("1 inch in cm", "2.54", 0);
+
+    /* Area */
+    test("1m² in mm²", "1000000", 0);
+  
+    /* Volume */
+    test("1m³ in mm³", "1000000000", 0);  
+
+    /* Weight */
+    test("1 kg in pounds", "2.204622622", 0);
+  
+    /* Time */
+    test("1 minute in seconds", "60", 0);
+}
+
+
 int
 variable_is_defined(const char *name)
 {
@@ -129,9 +156,8 @@ set_variable(const char *name, const MPNumber *x, void *data)
 {
 }
 
-
 void
-test_parser()
+test_equations()
 {
     memset(&options, 0, sizeof(options));
     base = 10;
@@ -645,6 +671,7 @@ unittest()
 {
     test_mp();
     test_numbers();
-    test_parser();
+    test_conversions();
+    test_equations();
     exit(fails > 0 ? 1 : 0);
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]