made formatting more consistent
This commit is contained in:
@@ -82,24 +82,24 @@ static const UnitDef *find_unit(const char *str) {
|
||||
size_t j = 0;
|
||||
|
||||
for (size_t i = 0; i < len && j < 63; i++) {
|
||||
if ((unsigned char)str[i] == 0xC2 && (unsigned char)str[i+1] == 0xB0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (str[i] == '^' && i + 1 < len && str[i + 1] == '2') {
|
||||
normalized[j++] = '2';
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
normalized[j++] = tolower((unsigned char)str[i]);
|
||||
if ((unsigned char)str[i] == 0xC2 && (unsigned char)str[i+1] == 0xB0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (str[i] == '^' && i + 1 < len && str[i + 1] == '2') {
|
||||
normalized[j++] = '2';
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
normalized[j++] = tolower((unsigned char)str[i]);
|
||||
}
|
||||
normalized[j] = '\0';
|
||||
|
||||
for (int i = 0; i < UNIT_COUNT; i++) {
|
||||
if (strcmp(normalized, UNITS[i].name) == 0) return &UNITS[i];
|
||||
for (int k = 0; k < 4 && UNITS[i].alias[k]; k++) {
|
||||
if (strcmp(normalized, UNITS[i].alias[k]) == 0) return &UNITS[i];
|
||||
}
|
||||
if (strcmp(normalized, UNITS[i].name) == 0) return &UNITS[i];
|
||||
for (int k = 0; k < 4 && UNITS[i].alias[k]; k++) {
|
||||
if (strcmp(normalized, UNITS[i].alias[k]) == 0) return &UNITS[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -108,37 +108,37 @@ int is_unit_conv_query(const char *query) {
|
||||
if (!query) return 0;
|
||||
|
||||
const char *patterns[] = {
|
||||
" to ", " in ", " into ",
|
||||
" = ", " equals ", " equal ",
|
||||
" convert ", " conversion ",
|
||||
" -> ", " → ",
|
||||
NULL
|
||||
" to ", " in ", " into ",
|
||||
" = ", " equals ", " equal ",
|
||||
" convert ", " conversion ",
|
||||
" -> ", " → ",
|
||||
NULL
|
||||
};
|
||||
|
||||
int has_pattern = 0;
|
||||
for (int i = 0; patterns[i]; i++) {
|
||||
if (strstr(query, patterns[i])) {
|
||||
has_pattern = 1;
|
||||
break;
|
||||
}
|
||||
if (strstr(query, patterns[i])) {
|
||||
has_pattern = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_pattern) {
|
||||
const char *last_space = strrchr(query, ' ');
|
||||
if (last_space) {
|
||||
const UnitDef *u = find_unit(last_space + 1);
|
||||
if (u) {
|
||||
const char *before = query;
|
||||
while (*before && is_whitespace(*before)) before++;
|
||||
const char *num_end = before;
|
||||
while (*num_end &&
|
||||
(isdigit(*num_end) || *num_end == '.' || *num_end == '-' ||
|
||||
*num_end == '+' || *num_end == '/' || *num_end == '\'' || *num_end == '"')) {
|
||||
num_end++;
|
||||
}
|
||||
if (num_end > before) has_pattern = 1;
|
||||
}
|
||||
const char *last_space = strrchr(query, ' ');
|
||||
if (last_space) {
|
||||
const UnitDef *u = find_unit(last_space + 1);
|
||||
if (u) {
|
||||
const char *before = query;
|
||||
while (*before && is_whitespace(*before)) before++;
|
||||
const char *num_end = before;
|
||||
while (*num_end &&
|
||||
(isdigit(*num_end) || *num_end == '.' || *num_end == '-' ||
|
||||
*num_end == '+' || *num_end == '/' || *num_end == '\'' || *num_end == '"')) {
|
||||
num_end++;
|
||||
}
|
||||
if (num_end > before) has_pattern = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return has_pattern;
|
||||
@@ -153,58 +153,58 @@ static double parse_value(const char **ptr) {
|
||||
|
||||
if (*p == '-' || *p == '+') p++;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
value = value * 10 + (*p - '0');
|
||||
value = value * 10 + (*p - '0');
|
||||
has_num = 1;
|
||||
p++;
|
||||
}
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
double frac = 0.1;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
value += (*p - '0') * frac;
|
||||
frac *= 0.1;
|
||||
has_num = 1;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == '/' && has_num) {
|
||||
p++;
|
||||
double denom = 0.0;
|
||||
int has_denom = 0;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
denom = denom * 10 + (*p - '0');
|
||||
has_denom = 1;
|
||||
p++;
|
||||
}
|
||||
if (has_denom && denom > 0) {
|
||||
value = value / denom;
|
||||
}
|
||||
}
|
||||
|
||||
while (*p == '\'' || *p == '"') {
|
||||
double extra = 0.0;
|
||||
p++;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
extra = extra * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
double frac = 0.1;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
value += (*p - '0') * frac;
|
||||
frac *= 0.1;
|
||||
has_num = 1;
|
||||
p++;
|
||||
extra += (*p - '0') * frac;
|
||||
frac *= 0.1;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == '/' && has_num) {
|
||||
p++;
|
||||
double denom = 0.0;
|
||||
int has_denom = 0;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
denom = denom * 10 + (*p - '0');
|
||||
has_denom = 1;
|
||||
p++;
|
||||
}
|
||||
if (has_denom && denom > 0) {
|
||||
value = value / denom;
|
||||
}
|
||||
}
|
||||
|
||||
while (*p == '\'' || *p == '"') {
|
||||
double extra = 0.0;
|
||||
p++;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
extra = extra * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
double frac = 0.1;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
extra += (*p - '0') * frac;
|
||||
frac *= 0.1;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
if (*p == '\'' || *p == '"') p++;
|
||||
value += extra * (p[-1] == '\'' ? 0.3048 : 0.0254);
|
||||
if (*p == '\'' || *p == '"') p++;
|
||||
value += extra * (p[-1] == '\'' ? 0.3048 : 0.0254);
|
||||
}
|
||||
|
||||
if (!has_num) {
|
||||
*ptr = p;
|
||||
return 0.0;
|
||||
*ptr = p;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
*ptr = p;
|
||||
@@ -235,29 +235,29 @@ static int parse_conversion_query(const char *query, double *value, const UnitDe
|
||||
const char *to_pos = NULL;
|
||||
size_t keyword_len = 0;
|
||||
for (int i = 0; to_keywords[i]; i++) {
|
||||
const char *found = strstr(p, to_keywords[i]);
|
||||
if (found) {
|
||||
to_pos = found + strlen(to_keywords[i]);
|
||||
keyword_len = strlen(to_keywords[i]);
|
||||
break;
|
||||
}
|
||||
const char *found = strstr(p, to_keywords[i]);
|
||||
if (found) {
|
||||
to_pos = found + strlen(to_keywords[i]);
|
||||
keyword_len = strlen(to_keywords[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!to_pos) {
|
||||
const char *last_space = strrchr(p, ' ');
|
||||
if (last_space && last_space > p) {
|
||||
char from_part[64] = {0};
|
||||
size_t len = last_space - p;
|
||||
if (len < 63) {
|
||||
strncpy(from_part, p, len);
|
||||
*from_unit = find_unit(from_part);
|
||||
if (*from_unit) {
|
||||
*to_unit = find_unit(last_space + 1);
|
||||
return *to_unit ? 1 : 0;
|
||||
}
|
||||
}
|
||||
const char *last_space = strrchr(p, ' ');
|
||||
if (last_space && last_space > p) {
|
||||
char from_part[64] = {0};
|
||||
size_t len = last_space - p;
|
||||
if (len < 63) {
|
||||
strncpy(from_part, p, len);
|
||||
*from_unit = find_unit(from_part);
|
||||
if (*from_unit) {
|
||||
*to_unit = find_unit(last_space + 1);
|
||||
return *to_unit ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char from_part[64] = {0};
|
||||
@@ -271,20 +271,20 @@ static int parse_conversion_query(const char *query, double *value, const UnitDe
|
||||
|
||||
*from_unit = find_unit(from_part);
|
||||
if (!*from_unit) {
|
||||
char *end = from_part + strlen(from_part);
|
||||
while (end > from_part) {
|
||||
while (end > from_part && is_whitespace(end[-1])) end--;
|
||||
if (end <= from_part) break;
|
||||
char *start = end;
|
||||
while (start > from_part && !is_whitespace(start[-1])) start--;
|
||||
size_t word_len = end - start;
|
||||
memmove(from_part + word_len + 1, from_part, start - from_part);
|
||||
from_part[word_len] = ' ';
|
||||
from_part[word_len + 1] = '\0';
|
||||
*from_unit = find_unit(from_part);
|
||||
if (*from_unit) break;
|
||||
end = start;
|
||||
}
|
||||
char *end = from_part + strlen(from_part);
|
||||
while (end > from_part) {
|
||||
while (end > from_part && is_whitespace(end[-1])) end--;
|
||||
if (end <= from_part) break;
|
||||
char *start = end;
|
||||
while (start > from_part && !is_whitespace(start[-1])) start--;
|
||||
size_t word_len = end - start;
|
||||
memmove(from_part + word_len + 1, from_part, start - from_part);
|
||||
from_part[word_len] = ' ';
|
||||
from_part[word_len + 1] = '\0';
|
||||
*from_unit = find_unit(from_part);
|
||||
if (*from_unit) break;
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*from_unit) return 0;
|
||||
@@ -297,30 +297,30 @@ static int parse_conversion_query(const char *query, double *value, const UnitDe
|
||||
size_t to_len = 0;
|
||||
const char *tp = to_pos;
|
||||
while (*tp && !is_separator(*tp) && to_len < 63) {
|
||||
to_part[to_len++] = *tp++;
|
||||
to_part[to_len++] = *tp++;
|
||||
}
|
||||
to_part[to_len] = '\0';
|
||||
|
||||
*to_unit = find_unit(to_part);
|
||||
if (!*to_unit) {
|
||||
const char *try_ptr = to_pos;
|
||||
while (*try_ptr && is_whitespace(*try_ptr)) try_ptr++;
|
||||
char try_buf[64] = {0};
|
||||
size_t try_len = 0;
|
||||
while (*try_ptr && try_len < 63) {
|
||||
try_buf[try_len++] = *try_ptr++;
|
||||
}
|
||||
while (try_len > 0) {
|
||||
*to_unit = find_unit(try_buf);
|
||||
if (*to_unit) {
|
||||
strcpy(to_part, try_buf);
|
||||
break;
|
||||
}
|
||||
char *last_space = strrchr(try_buf, ' ');
|
||||
if (!last_space) break;
|
||||
*last_space = '\0';
|
||||
try_len = strlen(try_buf);
|
||||
const char *try_ptr = to_pos;
|
||||
while (*try_ptr && is_whitespace(*try_ptr)) try_ptr++;
|
||||
char try_buf[64] = {0};
|
||||
size_t try_len = 0;
|
||||
while (*try_ptr && try_len < 63) {
|
||||
try_buf[try_len++] = *try_ptr++;
|
||||
}
|
||||
while (try_len > 0) {
|
||||
*to_unit = find_unit(try_buf);
|
||||
if (*to_unit) {
|
||||
strcpy(to_part, try_buf);
|
||||
break;
|
||||
}
|
||||
char *last_space = strrchr(try_buf, ' ');
|
||||
if (!last_space) break;
|
||||
*last_space = '\0';
|
||||
try_len = strlen(try_buf);
|
||||
}
|
||||
}
|
||||
|
||||
return *to_unit ? 1 : 0;
|
||||
@@ -343,7 +343,7 @@ static double convert_value(double value, const UnitDef *from, const UnitDef *to
|
||||
if (from->type != to->type) return 0;
|
||||
|
||||
if (from->type == UNIT_TEMP) {
|
||||
return convert_temp(value, from, to);
|
||||
return convert_temp(value, from, to);
|
||||
}
|
||||
|
||||
double base_value = value * from->to_base;
|
||||
@@ -353,23 +353,23 @@ static double convert_value(double value, const UnitDef *from, const UnitDef *to
|
||||
static void format_number(double val, char *buf, size_t bufsize) {
|
||||
if (bufsize == 0) return;
|
||||
if (val == 0) {
|
||||
snprintf(buf, bufsize, "0");
|
||||
return;
|
||||
snprintf(buf, bufsize, "0");
|
||||
return;
|
||||
}
|
||||
if (fabs(val) < 0.01 && fabs(val) > 0) {
|
||||
snprintf(buf, bufsize, "%.2g", val);
|
||||
snprintf(buf, bufsize, "%.2g", val);
|
||||
} else if (fabs(val) < 1) {
|
||||
snprintf(buf, bufsize, "%.2f", val);
|
||||
char *p = buf + strlen(buf) - 1;
|
||||
while (p > buf && *p == '0') *p-- = '\0';
|
||||
if (*p == '.') *p = '\0';
|
||||
snprintf(buf, bufsize, "%.2f", val);
|
||||
char *p = buf + strlen(buf) - 1;
|
||||
while (p > buf && *p == '0') *p-- = '\0';
|
||||
if (*p == '.') *p = '\0';
|
||||
} else if (fmod(val + 0.0001, 1.0) < 0.0002) {
|
||||
snprintf(buf, bufsize, "%.0f", val);
|
||||
snprintf(buf, bufsize, "%.0f", val);
|
||||
} else {
|
||||
snprintf(buf, bufsize, "%.2f", val);
|
||||
char *p = buf + strlen(buf) - 1;
|
||||
while (p > buf && *p == '0') *p-- = '\0';
|
||||
if (*p == '.') *p = '\0';
|
||||
snprintf(buf, bufsize, "%.2f", val);
|
||||
char *p = buf + strlen(buf) - 1;
|
||||
while (p > buf && *p == '0') *p-- = '\0';
|
||||
if (*p == '.') *p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,74 +383,74 @@ static const char *pluralize(const char *unit, double value, char *buf, size_t b
|
||||
buf[bufsize - 1] = '\0';
|
||||
|
||||
if (strcmp(unit, "foot") == 0 || strcmp(unit, "square foot") == 0) {
|
||||
if (is_one) strcpy(buf, unit);
|
||||
else strcpy(buf, strcmp(unit, "square foot") == 0 ? "square feet" : "feet");
|
||||
return buf;
|
||||
if (is_one) strcpy(buf, unit);
|
||||
else strcpy(buf, strcmp(unit, "square foot") == 0 ? "square feet" : "feet");
|
||||
return buf;
|
||||
}
|
||||
if (strcmp(unit, "inch") == 0 || strcmp(unit, "square inch") == 0) {
|
||||
if (is_one) strcpy(buf, unit);
|
||||
else strcpy(buf, strcmp(unit, "square inch") == 0 ? "square inches" : "inches");
|
||||
return buf;
|
||||
if (is_one) strcpy(buf, unit);
|
||||
else strcpy(buf, strcmp(unit, "square inch") == 0 ? "square inches" : "inches");
|
||||
return buf;
|
||||
}
|
||||
if (strcmp(unit, "stone") == 0) {
|
||||
if (is_one) strcpy(buf, "stone");
|
||||
else strcpy(buf, "stones");
|
||||
return buf;
|
||||
if (is_one) strcpy(buf, "stone");
|
||||
else strcpy(buf, "stones");
|
||||
return buf;
|
||||
}
|
||||
if (strcmp(unit, "celsius") == 0 ||
|
||||
strcmp(unit, "fahrenheit") == 0 ||
|
||||
strcmp(unit, "kelvin") == 0) {
|
||||
strcpy(buf, unit);
|
||||
return buf;
|
||||
strcmp(unit, "fahrenheit") == 0 ||
|
||||
strcmp(unit, "kelvin") == 0) {
|
||||
strcpy(buf, unit);
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (unit[len-1] == 's' ||
|
||||
unit[len-1] == 'x' ||
|
||||
unit[len-1] == 'z' ||
|
||||
(len >= 2 && unit[len-2] == 'c' && unit[len-1] == 'h') ||
|
||||
(len >= 2 && unit[len-2] == 's' && unit[len-1] == 'h')) {
|
||||
if (!is_one) {
|
||||
buf[len] = 'e';
|
||||
buf[len+1] = '\0';
|
||||
}
|
||||
unit[len-1] == 'x' ||
|
||||
unit[len-1] == 'z' ||
|
||||
(len >= 2 && unit[len-2] == 'c' && unit[len-1] == 'h') ||
|
||||
(len >= 2 && unit[len-2] == 's' && unit[len-1] == 'h')) {
|
||||
if (!is_one) {
|
||||
buf[len] = 'e';
|
||||
buf[len+1] = '\0';
|
||||
}
|
||||
} else if (unit[len-1] == 'y' && len >= 2 &&
|
||||
!(unit[len-2] == 'a' || unit[len-2] == 'e' ||
|
||||
unit[len-2] == 'i' || unit[len-2] == 'o' ||
|
||||
unit[len-2] == 'u')) {
|
||||
if (is_one) {
|
||||
buf[len-1] = '\0';
|
||||
} else {
|
||||
buf[len] = 's';
|
||||
buf[len+1] = '\0';
|
||||
}
|
||||
} else if (len >= 2 && unit[len-2] == 'f' && unit[len-1] == 'e') {
|
||||
if (is_one) {
|
||||
buf[len-2] = '\0';
|
||||
} else {
|
||||
buf[len-1] = 's';
|
||||
buf[len] = '\0';
|
||||
}
|
||||
} else if (unit[len-1] == 'f' && len >= 1) {
|
||||
if (is_one) {
|
||||
buf[len-1] = '\0';
|
||||
} else {
|
||||
buf[len-1] = 'v';
|
||||
buf[len] = 'e';
|
||||
buf[len+1] = 's';
|
||||
buf[len+2] = '\0';
|
||||
}
|
||||
} else if (unit[len-1] == 'e' && len >= 2 && unit[len-2] == 'f') {
|
||||
if (is_one) {
|
||||
buf[len-2] = '\0';
|
||||
} else {
|
||||
buf[len-1] = 's';
|
||||
buf[len] = '\0';
|
||||
}
|
||||
!(unit[len-2] == 'a' || unit[len-2] == 'e' ||
|
||||
unit[len-2] == 'i' || unit[len-2] == 'o' ||
|
||||
unit[len-2] == 'u')) {
|
||||
if (is_one) {
|
||||
buf[len-1] = '\0';
|
||||
} else {
|
||||
if (!is_one) {
|
||||
buf[len] = 's';
|
||||
buf[len+1] = '\0';
|
||||
}
|
||||
buf[len] = 's';
|
||||
buf[len+1] = '\0';
|
||||
}
|
||||
} else if (len >= 2 && unit[len-2] == 'f' && unit[len-1] == 'e') {
|
||||
if (is_one) {
|
||||
buf[len-2] = '\0';
|
||||
} else {
|
||||
buf[len-1] = 's';
|
||||
buf[len] = '\0';
|
||||
}
|
||||
} else if (unit[len-1] == 'f' && len >= 1) {
|
||||
if (is_one) {
|
||||
buf[len-1] = '\0';
|
||||
} else {
|
||||
buf[len-1] = 'v';
|
||||
buf[len] = 'e';
|
||||
buf[len+1] = 's';
|
||||
buf[len+2] = '\0';
|
||||
}
|
||||
} else if (unit[len-1] == 'e' && len >= 2 && unit[len-2] == 'f') {
|
||||
if (is_one) {
|
||||
buf[len-2] = '\0';
|
||||
} else {
|
||||
buf[len-1] = 's';
|
||||
buf[len] = '\0';
|
||||
}
|
||||
} else {
|
||||
if (!is_one) {
|
||||
buf[len] = 's';
|
||||
buf[len+1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
@@ -466,12 +466,12 @@ static char *build_html(double value, const UnitDef *from, double result, const
|
||||
pluralize(to->name, result, to_name_buf, sizeof(to_name_buf));
|
||||
|
||||
int n = snprintf(html, sizeof(html),
|
||||
"<div class='unit-conv-container' style='line-height: 1.6;'>"
|
||||
"<div style='font-size: 1.3em; margin-bottom: 8px;'>"
|
||||
"<b>%s %s</b> = <b>%s %s</b>"
|
||||
"</div>",
|
||||
val_buf, from_name_buf,
|
||||
res_buf, to_name_buf);
|
||||
"<div class='unit-conv-container' style='line-height: 1.6;'>"
|
||||
"<div style='font-size: 1.3em; margin-bottom: 8px;'>"
|
||||
"<b>%s %s</b> = <b>%s %s</b>"
|
||||
"</div>",
|
||||
val_buf, from_name_buf,
|
||||
res_buf, to_name_buf);
|
||||
snprintf(html + n, sizeof(html) - n, "</div>");
|
||||
return html;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user