35#define TEMP_STR_SIZE 256
45#define UN_SC_KM 1000.0f
46#define UN_SC_HM 100.0f
47#define UN_SC_DAM 10.0f
51#define UN_SC_MM 0.001f
52#define UN_SC_UM 0.000001f
55#define UN_SC_MI 1609.344f
56#define UN_SC_FUR 201.168f
57#define UN_SC_CH 20.1168f
58#define UN_SC_YD 0.9144f
59#define UN_SC_FT 0.3048f
60#define UN_SC_IN 0.0254f
61#define UN_SC_MIL 0.0000254f
64#define UN_SC_MTON 1000.0f
65#define UN_SC_QL 100.0f
68#define UN_SC_DAG 0.01f
70#define UN_SC_MG 0.000001f
73#define UN_SC_ITON 907.18474f
74#define UN_SC_CWT 45.359237f
75#define UN_SC_ST 6.35029318f
76#define UN_SC_LB 0.45359237f
77#define UN_SC_OZ 0.028349523125f
80#define UN_SC_FAH 0.555555555555f
134#define UNIT_COLLECTION_LENGTH(def) (ARRAY_SIZE(def) - 1)
461 "square hectometers",
464 "Square Hectometers",
506 "square centimeters",
509 "Square Centimeters",
517 "square millimeters",
520 "Square Millimeters",
528 "square micrometers",
531 "Square Micrometers",
995 "kilometer per hour",
996 "kilometers per hour",
999 "Kilometers per hour",
1051 "meter per second squared",
1052 "meters per second squared",
1055 "Meters per second squared",
1073 "foot per second squared",
1074 "feet per second squared",
1077 "Feet per second squared",
1191 (
M_PI / 180.0) / 60.0,
1202 (
M_PI / 180.0) / 3600.0,
1519#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1)
1598 double value_abs = value > 0.0 ? value : -value;
1600 for (
const bUnitDef *unit = unit_start ? unit_start : usys->
units; unit->
name; unit++) {
1608 if (value_abs >= unit->scalar * (0.1 -
EPS)) {
1613 if (value_abs >= unit->scalar * (1.0 -
EPS)) {
1633 const double scaled_value = value / unit->
scalar;
1634 *r_value_a = std::trunc(scaled_value) * unit->
scalar;
1635 *r_value_b = value - (*r_value_a);
1645 const bool do_rstrip_zero,
1652 if (unit ==
nullptr) {
1662 double value_conv = (value / unit->
scalar) - unit->
bias;
1682 if (do_rstrip_zero) {
1683 while (
i > 0 &&
str[
i] ==
'0') {
1687 if (
i > 0 &&
str[
i] ==
'.') {
1699 if (
i < str_maxncpy) {
1702 while (unit->
name_short[j] && (
i < str_maxncpy)) {
1708 if (
i >= str_maxncpy) {
1709 i = str_maxncpy - 1;
1747 const bool do_rstrip_zero,
1753 double value_a, value_b;
1754 unit_dual_convert(value, usys, &unit_a, &unit_b, &value_a, &value_b, main_unit);
1757 if (unit_b > unit_a) {
1759 size_t i =
unit_as_string(
str, str_maxncpy, value_a, prec,
true, usys, unit_a,
'\0');
1766 if (
i + 2 < str_maxncpy) {
1771 str +
i, str_maxncpy -
i, value_b, prec, do_rstrip_zero, usys, unit_b,
'\0');
1781 return usys !=
nullptr && usys->
units[0].
name !=
nullptr;
1791 int max_offset = usys->
length - 1;
1800 return usys->
units + std::min(units.
length, max_offset);
1805 return usys->
units + std::min(units.
mass, max_offset);
1810 return usys->
units + std::min(units.
time, max_offset);
1813 return usys->
units + 0;
1816 return usys->
units + 3;
1841 const bUnitDef *main_unit =
nullptr;
1850 bool do_rstrip_zero =
true;
1853 do_rstrip_zero =
false;
1858 str, str_maxncpy, value, prec, do_rstrip_zero, usys, main_unit);
1866 str, str_maxncpy, value, prec, do_rstrip_zero, usys, main_unit,
pad ?
' ' :
'\0');
1870 char *
str,
int str_maxncpy,
double value,
int prec,
int system,
int type,
bool split,
bool pad)
1914 switch (unit_type) {
1935 return (ch >= 128 || isalpha(ch));
1940 if (substr ==
nullptr || substr[0] ==
'\0') {
1946 const char *str_found;
1947 if (case_sensitive) {
1948 str_found = strstr(
str, substr);
1956 if (str_found ==
str ||
1962 int len_name = strlen(substr);
2033 const char *str_found = strstr(remaining_str,
"-");
2035 if (str_found ==
nullptr) {
2040 if ((str_found !=
str) &&
ELEM(*(str_found - 1),
'e',
'E')) {
2044 if (*(str_found + 1) ==
' ') {
2048 return str_found + 1;
2060 for (
i = 0;
i < remaining_str_maxncpy;
i++) {
2061 if (remaining_str[
i] ==
'\0') {
2062 return remaining_str +
i;
2067 if (remaining_str !=
str &&
i != 0) {
2069 if ((remaining_str[
i] ==
'/') &&
ELEM(remaining_str[
i - 1],
't',
'T',
'm',
'M') &&
2070 ELEM(remaining_str[
i + 1],
's',
'S'))
2076 if (
ELEM(remaining_str[
i - 1],
'e',
'E')) {
2081 if (remaining_str[
i - 1] ==
' ') {
2086 return remaining_str +
i;
2090 return remaining_str +
i;
2113 bool changed =
false;
2115 char *remaining_str =
str;
2117 int remaining_str_maxncpy;
2119 remaining_str_maxncpy = str_maxncpy - int(remaining_str -
str);
2120 if (remaining_str_maxncpy <= 2) {
2127 memmove(remaining_str + 1, remaining_str, remaining_str_maxncpy - 2);
2128 *remaining_str =
'(';
2133 remaining_str_maxncpy = str_maxncpy - int(remaining_str -
str);
2134 memmove(remaining_str + 1, remaining_str, remaining_str_maxncpy - 2);
2135 *remaining_str =
')';
2151 for (
int i = start_ofs;
i > 0;
i--) {
2166 for (
i = start_ofs;
i < str_maxncpy;
i++) {
2167 if (!strchr(
"0123456789eE.",
str[
i])) {
2179 const char *replace_str,
2180 bool case_sensitive)
2182 if (str_maxncpy < 0) {
2189 if (str_found ==
nullptr) {
2193 int found_ofs = int(str_found -
str);
2202 if (unit->
bias != 0.0) {
2205 if (
len + 1 < str_maxncpy) {
2206 memmove(
str + prev_op_ofs + 1,
str + prev_op_ofs,
len - prev_op_ofs + 1);
2207 str[prev_op_ofs] =
'(';
2216 if (value_end_ofs + len_bias_num < str_maxncpy) {
2217 memmove(
str + value_end_ofs + len_bias_num,
str + value_end_ofs,
len - value_end_ofs + 1);
2218 memcpy(
str + value_end_ofs, str_tmp, len_bias_num);
2219 len += len_bias_num;
2220 found_ofs += len_bias_num;
2221 str_found += len_bias_num;
2225 int len_name = strlen(replace_str);
2226 int len_move = (
len - (found_ofs + len_name)) + 1;
2232 len_num = std::min(len_num, str_maxncpy);
2234 if (found_ofs + len_num + len_move > str_maxncpy) {
2236 len_move -= (found_ofs + len_num + len_move) - str_maxncpy;
2242 memmove(str_found + len_num, str_found + len_name, len_move);
2245 if (found_ofs + len_num > str_maxncpy) {
2247 len_num -= (found_ofs + len_num) - str_maxncpy;
2252 memcpy(str_found, str_tmp, len_num);
2257 str[str_maxncpy - 1] =
'\0';
2258 return found_ofs + len_num;
2262 char *
str,
int str_maxncpy,
char *str_tmp,
double scale_pref,
const bUnitDef *unit)
2267 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->
name_short, case_sensitive);
2269 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->
name_plural,
false);
2271 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->
name_alt, case_sensitive);
2273 str + ofs, str_maxncpy - ofs, str_tmp, scale_pref, unit, unit->
name,
false);
2314 const char *str_prev)
2319 if (str_prev && (unit ==
nullptr)) {
2324 if (unit ==
nullptr) {
2352 const double bias = (unit ==
nullptr) ? 0.0 : unit->
bias;
2354 return value * scalar + bias;
2358 char *
str,
int str_maxncpy,
const char *str_prev,
double scale_pref,
int system,
int type)
2365 double scale_pref_base = scale_pref;
2367 bool changed =
false;
2377 scale_pref_base *= default_unit->
scalar;
2381 if (
SNPRINTF(str_tmp,
"(%s)*%.9g",
str, default_unit->
scalar) <
sizeof(str_tmp)) {
2392 while (
unit_replace(
str, str_maxncpy, str_tmp, scale_pref_base, unit)) {
2402 for (
int system_iter = 0; system_iter <
UNIT_SYSTEM_TOT; system_iter++) {
2403 if (system_iter == system) {
2407 if (usys_iter ==
nullptr) {
2414 while ((ofs =
unit_replace(
str + ofs, str_maxncpy - ofs, str_tmp, scale_pref_base, unit))) {
2425 char *str_found =
str;
2427 while ((str_found = strchr(str_found,
SEP_CHR))) {
2428 bool op_found =
false;
2431 for (
const char *ch = str_found + 1; *ch !=
'\0'; ch++) {
2432 if (
ELEM(*ch,
' ',
'\t')) {
2440 *str_found++ = op_found ?
' ' :
'+';
2452 for (
const bUnitDef *unit = usys->
units; unit->
name && (str_maxncpy > 0); unit++) {
2453 if (unit->name_alt ==
nullptr) {
2457 const char *found =
unit_find_str(orig_str, unit->name_short, case_sensitive);
2458 if (found ==
nullptr) {
2462 int offset = int(found - orig_str);
2465 if (offset < str_maxncpy) {
2466 memcpy(
str, orig_str, offset);
2470 offset = str_maxncpy;
2474 orig_str += offset + strlen(unit->name_short);
2475 str_maxncpy -= offset;
2481 str_maxncpy -= len_name;
2492 if (usys ==
nullptr) {
2497 if (unit ==
nullptr) {
2524 if (usys ==
nullptr) {
2560 BLI_assert_msg(0,
"identifier for this unit is not specified yet");
#define BLI_assert_msg(a, msg)
MINLINE int integer_digits_d(double d)
MINLINE int max_ii(int a, int b)
#define SNPRINTF(dst, format,...)
size_t BLI_snprintf_rlen(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char char size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
int char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
const char * BLI_str_find_prev_char_utf8(const char *p, const char *str_start) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1
#define BLI_STR_UTF8_DEGREE_SIGN
#define BLI_STR_UTF8_SUPERSCRIPT_2
#define BLI_STR_UTF8_SUPERSCRIPT_3
Compatibility-like things for windows.
#define USER_UNIT_ADAPTIVE
static void split(const char *text, const char *seps, char ***str, int *count)
int pad[32 - sizeof(int)]
float length(VecOp< float, D >) RET
const char * name_display
static bUnitCollection buCameraLenCollection
static const bUnitCollection * unit_get_system(int system, int type)
static bool ch_is_op_unary(char op)
void BKE_unit_name_to_alt(char *str, int str_maxncpy, const char *orig_str, int system, int type)
static bUnitCollection buImperialVolCollection
int BKE_unit_base_of_type_get(int system, int type)
static bUnitDef buImperialTempDef[]
static const bUnitCollection * bUnitSystems[][B_UNIT_TYPE_TOT]
static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings &settings)
static bUnitCollection buNaturalTimeCollection
static bUnitDef buImperialAclDef[]
static bUnitDef buWavelengthLenDef[]
bool BKE_unit_is_valid(int system, int type)
size_t BKE_unit_value_as_string(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings &settings, bool pad)
static bUnitCollection buMetricMassCollection
static const bUnitDef * unit_find_in_collection(const bUnitCollection *usys, const char *str)
size_t BKE_unit_value_as_string_scaled(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings &settings, bool pad)
static bUnitCollection buDummyCollection
static bUnitCollection buImperialVelCollection
static size_t unit_as_string_split_pair(char *str, int str_maxncpy, double value, int prec, const bool do_rstrip_zero, const bUnitCollection *usys, const bUnitDef *main_unit)
static bUnitDef buDummyDef[]
static void unit_dual_convert(double value, const bUnitCollection *usys, bUnitDef const **r_unit_a, bUnitDef const **r_unit_b, double *r_value_a, double *r_value_b, const bUnitDef *main_unit)
static bool is_valid_unit_collection(const bUnitCollection *usys)
const char * BKE_unit_identifier_get(const void *usys_pt, int index)
static bUnitDef buCameraLenDef[]
static bUnitCollection buImperialAreaCollection
bool BKE_unit_is_suppressed(const void *usys_pt, int index)
static bUnitCollection buNaturalRotCollection
#define UNIT_COLLECTION_LENGTH(def)
static bUnitDef buImperialMassDef[]
void BKE_unit_system_get(int system, int type, void const **r_usys_pt, int *r_len)
static bUnitCollection buImperialTempCollection
static bUnitCollection buImperialAclCollection
static bUnitCollection buImperialMassCollection
static bUnitDef buPowerDef[]
static int unit_scale_str(char *str, int str_maxncpy, char *str_tmp, double scale_pref, const bUnitDef *unit, const char *replace_str, bool case_sensitive)
static const bUnitDef * unit_best_fit(double value, const bUnitCollection *usys, const bUnitDef *unit_start, int suppress)
static char * find_next_op(const char *str, char *remaining_str, int remaining_str_maxncpy)
static bUnitCollection buMetricAclCollection
double BKE_unit_value_scale(const UnitSettings &settings, const int unit_type, double value)
const char * BKE_unit_display_name_get(const void *usys_pt, int index)
static bUnitDef buFrequencyDef[]
static bUnitCollection buColorTempCollection
static bool unit_find(const char *str, const bUnitDef *unit)
const char * BKE_unit_name_get(const void *usys_pt, int index)
int BKE_unit_base_get(const void *usys_pt)
bool BKE_unit_replace_string(char *str, int str_maxncpy, const char *str_prev, double scale_pref, int system, int type)
double BKE_unit_apply_preferred_unit(const UnitSettings &settings, int type, double value)
static int unit_replace(char *str, int str_maxncpy, char *str_tmp, double scale_pref, const bUnitDef *unit)
double BKE_unit_scalar_get(const void *usys_pt, int index)
static bUnitDef buMetricMassDef[]
static const char * find_next_negative(const char *str, const char *remaining_str)
static bool ch_is_op(char op)
static size_t unit_as_string(char *str, int str_maxncpy, double value, int prec, const bool do_rstrip_zero, const bUnitCollection *usys, const bUnitDef *unit, char pad)
static const bUnitDef * unit_detect_from_str(const bUnitCollection *usys, const char *str, const char *str_prev)
double BKE_unit_closest_scalar(double value, int system, int type)
static bUnitCollection buMetricAreaCollection
static bUnitDef buMetricVelDef[]
static const bUnitDef * unit_default(const bUnitCollection *usys)
static bUnitCollection buMetricVolCollection
static bool unit_distribute_negatives(char *str, const int str_maxncpy)
static int find_previous_non_value_char(const char *str, const int start_ofs)
static bUnitDef buNaturalRotDef[]
static bUnitDef buImperialAreaDef[]
static bUnitDef buImperialVelDef[]
static size_t unit_as_string_main(char *str, int str_maxncpy, double value, int prec, int type, bool split, bool pad, const PreferredUnits &units)
static const bUnitDef * get_preferred_display_unit_if_used(int type, const PreferredUnits &units)
double BKE_unit_base_scalar(int system, int type)
static bUnitDef buColorTempDef[]
static bUnitCollection buFrequencyCollection
static const char * unit_find_str(const char *str, const char *substr, bool case_sensitive)
static bUnitCollection buPowerCollection
bool BKE_unit_string_contains_unit(const char *str, int type)
size_t BKE_unit_value_as_string_adaptive(char *str, int str_maxncpy, double value, int prec, int system, int type, bool split, bool pad)
static bUnitDef buMetricAreaDef[]
static bUnitDef buMetricTempDef[]
static bUnitDef buMetricAclDef[]
static bUnitCollection buImperialLenCollection
static char * skip_unary_op(char *str)
static bUnitCollection buMetricTempCollection
static bUnitDef buMetricLenDef[]
static bUnitCollection buWavelengthLenCollection
static int find_end_of_value_chars(const char *str, const int str_maxncpy, const int start_ofs)
static bUnitDef buImperialVolDef[]
static bUnitDef buNaturalTimeDef[]
@ B_UNIT_DEF_CASE_SENSITIVE
static bUnitDef buImperialLenDef[]
static const bUnitCollection buMetricLenCollection
static bUnitCollection buMetricVelCollection
BLI_INLINE bool isalpha_or_utf8(const int ch)
static bool unit_should_be_split(int type)
static bUnitDef buMetricVolDef[]