From 56529d472f61dba8d01af27a792b5d14df1b2c2e Mon Sep 17 00:00:00 2001 From: Joseph Elliott Hand Date: Fri, 1 May 2026 17:25:39 -1000 Subject: Improve single unit identification - Refactor into separate function - Use array to store SI prefixes - Add remaining SI prefixes Signed-off-by: Joseph Elliott Hand --- unit.h | 101 ++++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/unit.h b/unit.h index a4c8b9d..32a26c0 100644 --- a/unit.h +++ b/unit.h @@ -29,6 +29,7 @@ double get_unit_value(char const * string); #include #include +#include #include #include @@ -37,6 +38,32 @@ typedef struct { double value; } Unit; +double unit_prefixes[255] = { + ['Q'] = 1e30, + ['R'] = 1e27, + ['Y'] = 1e24, + ['Z'] = 1e21, + ['E'] = 1e18, + ['P'] = 1e15, + ['T'] = 1e12, + ['G'] = 1e9, + ['M'] = 1e6, + ['k'] = 1e3, + ['h'] = 1e2, + ['d'] = 1e-1, + ['c'] = 1e-2, + ['m'] = 1e-3, + ['u'] = 1e-6, + ['n'] = 1e-9, + ['p'] = 1e-12, + ['f'] = 1e-15, + ['a'] = 1e-18, + ['z'] = 1e-21, + ['y'] = 1e-24, + ['r'] = 1e-27, + ['q'] = 1e-30 +}; + Unit units[] = { {"rad", 1}, @@ -141,6 +168,25 @@ get_token(char const * str, Token * token) { return -1; } +double +resolve_unit_name(char const * name) { + + double prefix_amount = unit_prefixes[name[0]]; + if(prefix_amount > 0) { + for (int j = 0; j < sizeof(units) / sizeof(units[0]); j++) { + if (strcmp(&name[1], units[j].abbr)) continue; + return prefix_amount * units[j].value; + } + } + + for (int j = 0; j < sizeof(units) / sizeof(units[0]); j++) { + if (strcmp(name, units[j].abbr)) continue; + return units[j].value; + } + + return 0.0; +} + double get_unit_value(char const * string) { @@ -190,56 +236,8 @@ get_unit_value(char const * string) { if (tokens[i].type != NAME) goto error; - double unit_value = 0.0f; - - for (int j = 0; j < sizeof(units) / sizeof(units[0]); j++) { - if (!strcmp(&tokens[i].value.str[1], units[j].abbr)) { - unit_value = units[j].value; - switch (tokens[i].value.str[0]) { - case 'k': - unit_value *= 1e3; - break; - case 'M': - unit_value *= 1e6; - break; - case 'G': - unit_value *= 1e9; - break; - case 'T': - unit_value *= 1e12; - break; - case 'c': - unit_value *= 1e-2; - break; - case 'm': - unit_value *= 1e-3; - break; - case 'u': - unit_value *= 1e-6; - break; - case 'n': - unit_value *= 1e-9; - break; - case 'p': - unit_value *= 1e-12; - break; - default: - goto error; - } - goto unit_found; - } - } - - for (int j = 0; j < sizeof(units) / sizeof(units[0]); j++) { - if (!strcmp(tokens[i].value.str, units[j].abbr)) { - unit_value = units[j].value; - goto unit_found; - } - } - - goto error; - - unit_found: + double unit_value = resolve_unit_name(tokens[i].value.str); + if(unit_value == 0.0) goto error; if (token_count <= i+1 || tokens[i + 1].type != EXP) { value *= pow(unit_value, exp_sign); @@ -256,8 +254,7 @@ get_unit_value(char const * string) { return value; error: - - fprintf(stderr, "unit.h: Invalid unit string: %s", string); + fprintf(stderr, "unit.h: Invalid unit string: %s\n", string); return 0; } -- cgit v1.2.3