aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Elliott Hand <jhand@hawaii.edu>2026-05-01 17:25:39 -1000
committerJoseph Elliott Hand <jhand@hawaii.edu>2026-05-01 17:25:39 -1000
commit56529d472f61dba8d01af27a792b5d14df1b2c2e (patch)
tree550a46a6aa3811030ae74ac67b2980d11cec9dc1
parent5de6eb0fe2c09dcc7decebf027085a2efbc92dfd (diff)
downloadunit.h-56529d472f61dba8d01af27a792b5d14df1b2c2e.tar.gz
Improve single unit identification
- Refactor into separate function - Use array to store SI prefixes - Add remaining SI prefixes Signed-off-by: Joseph Elliott Hand <jhand@hawaii.edu>
-rw-r--r--unit.h101
1 files 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 <math.h>
#include <regex.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -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},
@@ -142,6 +169,25 @@ get_token(char const * str, Token * token) {
}
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) {
int offset = 0;
@@ -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;
}