Index: trunk/src/librnd/core/rnd_printf.c =================================================================== --- trunk/src/librnd/core/rnd_printf.c (revision 34703) +++ trunk/src/librnd/core/rnd_printf.c (revision 34704) @@ -207,13 +207,14 @@ /* Determine scale factor -- find smallest unit that brings * the whole group above unity */ for (n = 0; n < rnd_get_n_units(); ++n) { - if (rnd_units[n].is_alias) + const rnd_unit_t *u = rnd_units.array[n]; + if (u->is_alias) continue; - if ((rnd_units[n].allow & allow) != 0 && (rnd_units[n].family == family)) { + if (((u->allow & allow) != 0) && (u->family == family)) { int n_above_one = 0; for (i = 0; i < n_coords; ++i) - if (fabs(value[i] * rnd_units[n].scale_factor) > 1) + if (fabs(value[i] * u->scale_factor) > 1) ++n_above_one; if (n_above_one == n_coords) break; @@ -221,18 +222,29 @@ } /* If nothing worked, wind back to the smallest allowable unit */ if (n == rnd_get_n_units()) { + const rnd_unit_t *u; do { --n; - } while ((n>=0) && ((rnd_units[n].allow & allow) == 0 || rnd_units[n].family != family) || rnd_units[n].is_alias); + if (n < 0) + break; + u = rnd_units.array[n]; + } while (u->is_alias || ((u->allow & allow) == 0) || (u->family != family)); } + if (n < 0) + return -1; + /* Apply scale factor */ - suffix = rnd_units[n].suffix; - for (i = 0; i < n_coords; ++i) - value[i] = value[i] * rnd_units[n].scale_factor; + { + const rnd_unit_t *u = rnd_units.array[n]; + suffix = u->suffix; + for(i = 0; i < n_coords; ++i) + value[i] = value[i] * u->scale_factor; - make_printf_spec(printf_spec_new, printf_spec, rnd_units[n].default_prec, &trunc0); + make_printf_spec(printf_spec_new, printf_spec, u->default_prec, &trunc0); + } + /* Actually sprintf the values in place * (+ 2 skips the ", " for first value) */ if (n_coords > 1) @@ -765,8 +777,9 @@ { int found = 0; for (i = 0; i < rnd_get_n_units(); ++i) { - if (strcmp(ext_unit, rnd_units[i].suffix) == 0) { - if (CoordsToString(string, value, 1, &spec, rnd_units[i].allow, suffix) != 0) goto err; + const rnd_unit_t *u = rnd_units.array[i]; + if (strcmp(ext_unit, u->suffix) == 0) { + if (CoordsToString(string, value, 1, &spec, u->allow, suffix) != 0) goto err; found = 1; break; } @@ -817,8 +830,9 @@ { int found = 0; for (i = 0; i < rnd_get_n_units(); ++i) { - if (*fmt == rnd_units[i].printf_code) { - if (CoordsToString(string, value, 1, &spec, rnd_units[i].allow, suffix) != 0) goto err; + const rnd_unit_t *u = rnd_units.array[i]; + if (*fmt == u->printf_code) { + if (CoordsToString(string, value, 1, &spec, u->allow, suffix) != 0) goto err; found = 1; break; } Index: trunk/src/librnd/core/unit.c =================================================================== --- trunk/src/librnd/core/unit.c (revision 34703) +++ trunk/src/librnd/core/unit.c (revision 34704) @@ -38,9 +38,11 @@ #include #include +vtp0_t rnd_units; + /* Should be kept in order of smallest scale_factor to largest -- the code uses this ordering for finding the best scale to use for a group of units */ -rnd_unit_t rnd_units[] = { +static rnd_unit_t rnd_unit_tbl[] = { {"km", 'k', 0.000001, RND_UNIT_METRIC, RND_UNIT_ALLOW_KM, 5, 0}, {"m", 'f', 0.001, RND_UNIT_METRIC, RND_UNIT_ALLOW_M, 5, 0}, {"cm", 'e', 0.1, RND_UNIT_METRIC, RND_UNIT_ALLOW_CM, 5, 0}, @@ -67,15 +69,29 @@ {"pcb", 0, 100, RND_UNIT_IMPERIAL, RND_UNIT_ALLOW_CMIL, 0, 1} /* old io_pcb unit */ }; -#define N_UNITS ((int) (sizeof rnd_units / sizeof rnd_units[0])) +#define UNIT_TBL_LEN ((int) (sizeof(rnd_unit_tbl) / sizeof(rnd_unit_tbl[0]))) void rnd_units_init(void) { int i; - for (i = 0; i < N_UNITS; ++i) - rnd_units[i].index = i; + +/* Initial allocation to avoid reallocs. Since rnd_unit_allow_t may + be 32 bit bitfield, generally there would be at most 32 types and their + aliases, so this buffer doesn't need to be too large. */ + vtp0_enlarge(&rnd_units, 128); + rnd_units.used = 0; + + for (i = 0; i < UNIT_TBL_LEN; ++i) { + rnd_unit_tbl[i].index = i; + vtp0_append(&rnd_units, &rnd_unit_tbl[i]); + } } +void rnd_units_uninit(void) +{ + vtp0_uninit(&rnd_units); +} + const rnd_unit_t *rnd_get_unit_struct_(const char *suffix, int strict) { int i; @@ -99,14 +115,18 @@ if (s_len <= 0) return NULL; - for (i = 0; i < N_UNITS; ++i) - if (strcmp(suffix, rnd_units[i].suffix) == 0) - return &rnd_units[i]; + for (i = 0; i < rnd_units.used; ++i) { + const rnd_unit_t *u = rnd_units.array[i]; + if (strcmp(suffix, u->suffix) == 0) + return u; + } if (!strict) { - for (i = 0; i < N_UNITS; ++i) - if (strncmp(suffix, rnd_units[i].suffix, s_len) == 0) - return &rnd_units[i]; + for (i = 0; i < rnd_units.used; ++i) { + const rnd_unit_t *u = rnd_units.array[i]; + if (strncmp(suffix, u->suffix, s_len) == 0) + return u; + } } return NULL; @@ -121,9 +141,11 @@ const rnd_unit_t *rnd_get_unit_struct_by_allow(rnd_unit_allow_t allow) { int i; - for (i = 0; i < N_UNITS; ++i) - if (rnd_units[i].allow == allow) - return &rnd_units[i]; + for (i = 0; i < rnd_units.used; ++i) { + const rnd_unit_t *u = rnd_units.array[i]; + if (u->allow == allow) + return u; + } return NULL; } @@ -130,23 +152,25 @@ const rnd_unit_t *rnd_unit_get_idx(int idx) { - if ((idx < 0) || (idx >= N_UNITS)) + if ((idx < 0) || (idx >= rnd_units.used)) return NULL; - return rnd_units + idx; + return rnd_units.array[idx]; } const rnd_unit_t *rnd_unit_get_suffix(const char *suffix) { int i; - for (i = 0; i < N_UNITS; ++i) - if (strcmp(rnd_units[i].suffix, suffix) == 0) - return &rnd_units[i]; + for (i = 0; i < rnd_units.used; ++i) { + const rnd_unit_t *u = rnd_units.array[i]; + if (strcmp(u->suffix, suffix) == 0) + return u; + } return NULL; } int rnd_get_n_units() { - return N_UNITS; + return rnd_units.used; } double rnd_coord_to_unit(const rnd_unit_t *unit, rnd_coord_t x) Index: trunk/src/librnd/core/unit.h =================================================================== --- trunk/src/librnd/core/unit.h (revision 34703) +++ trunk/src/librnd/core/unit.h (revision 34704) @@ -36,6 +36,7 @@ #define RND_UNIT_H #include +#include /*** Static units - these are hardwired because they are needed by most apps ***/ enum rnd_unit_allow_e { @@ -115,7 +116,7 @@ int index; /* Index into the rnd_units vector */ }; -extern rnd_unit_t rnd_units[]; +extern vtp0_t rnd_units; /* of (const rnd_unit_t *) elements */ /* Look up a given suffix in the units array. Pluralized units are supported. The _ version allows strict (full name match) lookup if strict iz non-zero. */ @@ -148,9 +149,9 @@ /* Initialize non-static unit data: assigns each unit its index for - quick access through the main units array, and internationalize - the units for GUI display. */ + quick access through the main units vector */ void rnd_units_init(void); +void rnd_units_uninit(void); /* internal<->physical unit conversions */ #define RND_COORD_TO_MIL(n) ((n) / 25400.0) Index: trunk/src/librnd/hid/hid_init.c =================================================================== --- trunk/src/librnd/hid/hid_init.c (revision 34703) +++ trunk/src/librnd/hid/hid_init.c (revision 34704) @@ -638,6 +638,7 @@ void rnd_hidlib_init2(const pup_buildin_t *buildins, const pup_buildin_t *local_buildins) { + rnd_units_init(); rnd_actions_init(); /* load custom config files in the order they were specified */ @@ -687,7 +688,6 @@ pup_autoload_dir(&rnd_pup, NULL, NULL); rnd_conf_load_extra(NULL, NULL); - rnd_units_init(); rnd_funchash_init(); rnd_anyload_act_init2(); @@ -744,6 +744,7 @@ rnd_hid_cfg_keys_uninit_module(); rnd_anyload_uninit(); rnd_events_uninit(); + rnd_units_uninit(); } /* parse arguments using the gui; if fails and fallback is enabled, try the next gui */ Index: trunk/tests/rnd_printf/tester.c =================================================================== --- trunk/tests/rnd_printf/tester.c (revision 34703) +++ trunk/tests/rnd_printf/tester.c (revision 34704) @@ -29,6 +29,7 @@ int n, rep; setlocale(LC_ALL, "C"); + rnd_units_init(); for(rep = 0; rep < NUMREP; rep++) { for(n = 0; n < sizeof(c) / sizeof(c[0]); n++) { @@ -69,6 +70,9 @@ printf("Average prints per second: %.4f\n", (double)pc/spent); } #endif + + rnd_units_uninit(); + return 0; }