From 24cec7a35072ac50e1fe902a925e69330866dbca Mon Sep 17 00:00:00 2001 From: frosty Date: Thu, 5 Mar 2026 04:50:32 +0000 Subject: made formatting more consistent --- src/Infobox/Calculator.c | 168 +++++++++--------- src/Infobox/Dictionary.c | 376 ++++++++++++++++++++--------------------- src/Infobox/Infobox.c | 16 +- src/Infobox/Infobox.h | 8 +- src/Infobox/UnitConversion.c | 394 +++++++++++++++++++++---------------------- src/Infobox/Wikipedia.c | 144 ++++++++-------- 6 files changed, 553 insertions(+), 553 deletions(-) (limited to 'src/Infobox') diff --git a/src/Infobox/Calculator.c b/src/Infobox/Calculator.c index b80ce21..22563f7 100644 --- a/src/Infobox/Calculator.c +++ b/src/Infobox/Calculator.c @@ -8,108 +8,108 @@ static char logic_log[4096]; typedef struct { - const char *buffer; - int pos; + const char *buffer; + int pos; } Parser; static double parse_expression(Parser *p); static void skip_ws(Parser *p) { - while (p->buffer[p->pos] == ' ') p->pos++; + while (p->buffer[p->pos] == ' ') p->pos++; } static double parse_factor(Parser *p) { - skip_ws(p); - if (p->buffer[p->pos] == '-') { - p->pos++; - return -parse_factor(p); - } - if (p->buffer[p->pos] == '(') { - p->pos++; - double res = parse_expression(p); - if (p->buffer[p->pos] == ')') p->pos++; - return res; - } - char *endptr; - double val = strtod(&p->buffer[p->pos], &endptr); - p->pos = (int)(endptr - p->buffer); - return val; + skip_ws(p); + if (p->buffer[p->pos] == '-') { + p->pos++; + return -parse_factor(p); + } + if (p->buffer[p->pos] == '(') { + p->pos++; + double res = parse_expression(p); + if (p->buffer[p->pos] == ')') p->pos++; + return res; + } + char *endptr; + double val = strtod(&p->buffer[p->pos], &endptr); + p->pos = (int)(endptr - p->buffer); + return val; } static double parse_term(Parser *p) { - double left = parse_factor(p); - while (1) { - skip_ws(p); - char op = p->buffer[p->pos]; - if (op == '*' || op == '/') { - p->pos++; - double right = parse_factor(p); - double old = left; - left = (op == '*') ? left * right : left / right; - - char step[256]; - - snprintf(step, sizeof(step), "
%g %c %g = %g
", old, op, - right, left); - strncat(logic_log, step, sizeof(logic_log) - strlen(logic_log) - 1); - } else - break; - } - return left; + double left = parse_factor(p); + while (1) { + skip_ws(p); + char op = p->buffer[p->pos]; + if (op == '*' || op == '/') { + p->pos++; + double right = parse_factor(p); + double old = left; + left = (op == '*') ? left * right : left / right; + + char step[256]; + + snprintf(step, sizeof(step), "
%g %c %g = %g
", old, op, + right, left); + strncat(logic_log, step, sizeof(logic_log) - strlen(logic_log) - 1); + } else + break; + } + return left; } static double parse_expression(Parser *p) { - double left = parse_term(p); - while (1) { - skip_ws(p); - char op = p->buffer[p->pos]; - if (op == '+' || op == '-') { - p->pos++; - double right = parse_term(p); - double old = left; - left = (op == '+') ? left + right : left - right; - - char step[256]; - - snprintf(step, sizeof(step), "
%g %c %g = %g
", old, op, - right, left); - strncat(logic_log, step, sizeof(logic_log) - strlen(logic_log) - 1); - } else - break; - } - return left; + double left = parse_term(p); + while (1) { + skip_ws(p); + char op = p->buffer[p->pos]; + if (op == '+' || op == '-') { + p->pos++; + double right = parse_term(p); + double old = left; + left = (op == '+') ? left + right : left - right; + + char step[256]; + + snprintf(step, sizeof(step), "
%g %c %g = %g
", old, op, + right, left); + strncat(logic_log, step, sizeof(logic_log) - strlen(logic_log) - 1); + } else + break; + } + return left; } double evaluate(const char *expr) { - logic_log[0] = '\0'; - if (!expr || strlen(expr) == 0) return 0.0; - Parser p = {expr, 0}; - return parse_expression(&p); + logic_log[0] = '\0'; + if (!expr || strlen(expr) == 0) return 0.0; + Parser p = {expr, 0}; + return parse_expression(&p); } InfoBox fetch_calc_data(char *math_input) { - InfoBox info = {NULL, NULL, NULL, NULL}; - if (!math_input) return info; - - double result = evaluate(math_input); - - char html_output[5120]; - snprintf(html_output, sizeof(html_output), - "
" - "%s" - "
" - "%g" - "
" - "
", - strlen(logic_log) > 0 ? logic_log : "
Constant value
", - result); - - info.title = strdup("Calculation"); - info.extract = strdup(html_output); - info.thumbnail_url = - strdup("/static/calculation.svg"); - info.url = strdup("#"); - - return info; + InfoBox info = {NULL, NULL, NULL, NULL}; + if (!math_input) return info; + + double result = evaluate(math_input); + + char html_output[5120]; + snprintf(html_output, sizeof(html_output), + "
" + "%s" + "
" + "%g" + "
" + "
", + strlen(logic_log) > 0 ? logic_log : "
Constant value
", + result); + + info.title = strdup("Calculation"); + info.extract = strdup(html_output); + info.thumbnail_url = + strdup("/static/calculation.svg"); + info.url = strdup("#"); + + return info; } diff --git a/src/Infobox/Dictionary.c b/src/Infobox/Dictionary.c index ca4e5cd..1900c21 100644 --- a/src/Infobox/Dictionary.c +++ b/src/Infobox/Dictionary.c @@ -11,239 +11,239 @@ #include static const char *PREFIXES[] = { - "what is the definition of ", "what's the definition of ", - "what is the meaning of ", "what's the meaning of ", - "what does the word ", "definition of ", "meaning of ", "def of ", - "define ", "definition ", "define:", "def ", "def:", - "what does ", "what is ", "what's ", "whats ", - "meaning ", "dictionary ", "dict ", NULL + "what is the definition of ", "what's the definition of ", + "what is the meaning of ", "what's the meaning of ", + "what does the word ", "definition of ", "meaning of ", "def of ", + "define ", "definition ", "define:", "def ", "def:", + "what does ", "what is ", "what's ", "whats ", + "meaning ", "dictionary ", "dict ", NULL }; static const char *SUFFIXES[] = { - " definition", " def", " meaning", " mean", " means", - " dictionary", " dict", " define", " defined", - " definition?", " def?", " meaning?", " mean?", " means?", - " in english", " in english?", NULL + " definition", " def", " meaning", " mean", " means", + " dictionary", " dict", " define", " defined", + " definition?", " def?", " meaning?", " mean?", " means?", + " in english", " in english?", NULL }; static const char *SKIP_WORDS[] = {"of ", "the ", "a ", "an ", NULL}; static const char *strcasestr_impl(const char *haystack, const char *needle) { - if (!haystack || !needle || !*needle) return haystack; - size_t len = strlen(needle); - for (const char *h = haystack; *h; h++) { - if (strncasecmp(h, needle, len) == 0) return h; - } - return NULL; + if (!haystack || !needle || !*needle) return haystack; + size_t len = strlen(needle); + for (const char *h = haystack; *h; h++) { + if (strncasecmp(h, needle, len) == 0) return h; + } + return NULL; } struct MemStruct { char *memory; size_t size; }; static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { - size_t realsize = size * nmemb; - struct MemStruct *mem = (struct MemStruct *)userp; - char *ptr = realloc(mem->memory, mem->size + realsize + 1); - if (!ptr) return 0; - mem->memory = ptr; - memcpy(&(mem->memory[mem->size]), contents, realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - return realsize; + size_t realsize = size * nmemb; + struct MemStruct *mem = (struct MemStruct *)userp; + char *ptr = realloc(mem->memory, mem->size + realsize + 1); + if (!ptr) return 0; + mem->memory = ptr; + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + return realsize; } static char *xpath_text(xmlDocPtr doc, const char *xpath) { - xmlXPathContextPtr ctx = xmlXPathNewContext(doc); - if (!ctx) return NULL; - xmlXPathObjectPtr obj = xmlXPathEvalExpression((const xmlChar *)xpath, ctx); - xmlXPathFreeContext(ctx); - if (!obj || !obj->nodesetval || obj->nodesetval->nodeNr == 0) { - if (obj) xmlXPathFreeObject(obj); - return NULL; - } - xmlChar *content = xmlNodeGetContent(obj->nodesetval->nodeTab[0]); - char *result = content ? strdup((char *)content) : NULL; - if (content) xmlFree(content); - xmlXPathFreeObject(obj); - return result; + xmlXPathContextPtr ctx = xmlXPathNewContext(doc); + if (!ctx) return NULL; + xmlXPathObjectPtr obj = xmlXPathEvalExpression((const xmlChar *)xpath, ctx); + xmlXPathFreeContext(ctx); + if (!obj || !obj->nodesetval || obj->nodesetval->nodeNr == 0) { + if (obj) xmlXPathFreeObject(obj); + return NULL; + } + xmlChar *content = xmlNodeGetContent(obj->nodesetval->nodeTab[0]); + char *result = content ? strdup((char *)content) : NULL; + if (content) xmlFree(content); + xmlXPathFreeObject(obj); + return result; } static char *build_html(const char *word, const char *pron, const char *pos, - const char *def, const char *ex) { - char html[4096]; - int n = snprintf(html, sizeof(html), "
"); - if (word) n += snprintf(html + n, sizeof(html) - n, - "
%s
", word); - if (pron) n += snprintf(html + n, sizeof(html) - n, - "
/%s/
", pron); - if (pos) n += snprintf(html + n, sizeof(html) - n, - "
%s
", pos); - if (def) n += snprintf(html + n, sizeof(html) - n, - "
%s
", def); - if (ex) n += snprintf(html + n, sizeof(html) - n, - "
\"%s\"
", ex); - snprintf(html + n, sizeof(html) - n, "
"); - return strdup(html); + const char *def, const char *ex) { + char html[4096]; + int n = snprintf(html, sizeof(html), "
"); + if (word) n += snprintf(html + n, sizeof(html) - n, + "
%s
", word); + if (pron) n += snprintf(html + n, sizeof(html) - n, + "
/%s/
", pron); + if (pos) n += snprintf(html + n, sizeof(html) - n, + "
%s
", pos); + if (def) n += snprintf(html + n, sizeof(html) - n, + "
%s
", def); + if (ex) n += snprintf(html + n, sizeof(html) - n, + "
\"%s\"
", ex); + snprintf(html + n, sizeof(html) - n, "
"); + return strdup(html); } static char *extract_word(const char *query) { - if (!query) return NULL; + if (!query) return NULL; - const char *start = query; + const char *start = query; - for (int i = 0; PREFIXES[i]; i++) { - size_t len = strlen(PREFIXES[i]); - if (strncasecmp(start, PREFIXES[i], len) == 0) { - start += len; - break; - } + for (int i = 0; PREFIXES[i]; i++) { + size_t len = strlen(PREFIXES[i]); + if (strncasecmp(start, PREFIXES[i], len) == 0) { + start += len; + break; } - - while (*start == ' ') start++; - char *word = strdup(start); - if (!word) return NULL; - - int changed = 1; - while (changed) { - changed = 0; - for (int i = 0; SKIP_WORDS[i]; i++) { - size_t len = strlen(SKIP_WORDS[i]); - if (strncasecmp(word, SKIP_WORDS[i], len) == 0) { - memmove(word, word + len, strlen(word + len) + 1); - changed = 1; - break; - } - } + } + + while (*start == ' ') start++; + char *word = strdup(start); + if (!word) return NULL; + + int changed = 1; + while (changed) { + changed = 0; + for (int i = 0; SKIP_WORDS[i]; i++) { + size_t len = strlen(SKIP_WORDS[i]); + if (strncasecmp(word, SKIP_WORDS[i], len) == 0) { + memmove(word, word + len, strlen(word + len) + 1); + changed = 1; + break; + } } + } - changed = 1; - while (changed) { - changed = 0; - for (int i = 0; SUFFIXES[i]; i++) { - const char *found = strcasestr_impl(word, SUFFIXES[i]); - if (found) { - char *pos = word + (found - word); - *pos = '\0'; - changed = 1; - break; - } - } + changed = 1; + while (changed) { + changed = 0; + for (int i = 0; SUFFIXES[i]; i++) { + const char *found = strcasestr_impl(word, SUFFIXES[i]); + if (found) { + char *pos = word + (found - word); + *pos = '\0'; + changed = 1; + break; + } } + } - size_t len = strlen(word); - while (len > 0 && (word[len-1] == ' ' || word[len-1] == '?' || - word[len-1] == '!' || word[len-1] == '.')) { - word[--len] = '\0'; - } + size_t len = strlen(word); + while (len > 0 && (word[len-1] == ' ' || word[len-1] == '?' || + word[len-1] == '!' || word[len-1] == '.')) { + word[--len] = '\0'; + } - if (len == 0) { free(word); return NULL; } + if (len == 0) { free(word); return NULL; } - for (size_t i = 0; i < len; i++) word[i] = tolower((unsigned char)word[i]); - char *space = strchr(word, ' '); - if (space) *space = '\0'; + for (size_t i = 0; i < len; i++) word[i] = tolower((unsigned char)word[i]); + char *space = strchr(word, ' '); + if (space) *space = '\0'; - return word; + return word; } int is_dictionary_query(const char *query) { - if (!query) return 0; - - for (int i = 0; PREFIXES[i]; i++) { - size_t len = strlen(PREFIXES[i]); - if (strncasecmp(query, PREFIXES[i], len) == 0) { - const char *after = query + len; - while (*after == ' ') after++; - if (*after != '\0') return 1; - } + if (!query) return 0; + + for (int i = 0; PREFIXES[i]; i++) { + size_t len = strlen(PREFIXES[i]); + if (strncasecmp(query, PREFIXES[i], len) == 0) { + const char *after = query + len; + while (*after == ' ') after++; + if (*after != '\0') return 1; } - - for (int i = 0; SUFFIXES[i]; i++) { - const char *pos = strcasestr_impl(query, SUFFIXES[i]); - if (pos) { - const char *after = pos + strlen(SUFFIXES[i]); - while (*after == ' ' || *after == '?' || *after == '!' || *after == '.') after++; - if (*after == '\0' && pos > query && (pos - query) < 100) return 1; - } + } + + for (int i = 0; SUFFIXES[i]; i++) { + const char *pos = strcasestr_impl(query, SUFFIXES[i]); + if (pos) { + const char *after = pos + strlen(SUFFIXES[i]); + while (*after == ' ' || *after == '?' || *after == '!' || *after == '.') after++; + if (*after == '\0' && pos > query && (pos - query) < 100) return 1; } - - if (strncasecmp(query, "what is ", 8) == 0 || - strncasecmp(query, "what's ", 7) == 0 || - strncasecmp(query, "whats ", 6) == 0) { - const char *word = query + (strncasecmp(query, "what is ", 8) == 0 ? 8 : - strncasecmp(query, "what's ", 7) == 0 ? 7 : 6); - const char *articles[] = {"the ", "your ", "my ", "his ", "her ", "their ", - "our ", "this ", "that ", "these ", "those ", "a ", "an ", NULL}; - for (int i = 0; articles[i]; i++) { - if (strncasecmp(word, articles[i], strlen(articles[i])) == 0) return 0; - } - const char *space = strchr(word, ' '); - if (!space || *(space + 1) == '\0' || *(space + 1) == '?') return 1; + } + + if (strncasecmp(query, "what is ", 8) == 0 || + strncasecmp(query, "what's ", 7) == 0 || + strncasecmp(query, "whats ", 6) == 0) { + const char *word = query + (strncasecmp(query, "what is ", 8) == 0 ? 8 : + strncasecmp(query, "what's ", 7) == 0 ? 7 : 6); + const char *articles[] = {"the ", "your ", "my ", "his ", "her ", "their ", + "our ", "this ", "that ", "these ", "those ", "a ", "an ", NULL}; + for (int i = 0; articles[i]; i++) { + if (strncasecmp(word, articles[i], strlen(articles[i])) == 0) return 0; } + const char *space = strchr(word, ' '); + if (!space || *(space + 1) == '\0' || *(space + 1) == '?') return 1; + } - return 0; + return 0; } char *construct_dictionary_url(const char *query) { - char *word = extract_word(query); - if (!word) return NULL; - - CURL *curl = curl_easy_init(); - if (!curl) { free(word); return NULL; } - - char *escaped = curl_easy_escape(curl, word, 0); - const char *base = "https://dictionary.cambridge.org/dictionary/english/"; - char *url = malloc(strlen(base) + strlen(escaped) + 1); - if (url) { - strcpy(url, base); - strcat(url, escaped); - } - - curl_free(escaped); - curl_easy_cleanup(curl); - free(word); - return url; + char *word = extract_word(query); + if (!word) return NULL; + + CURL *curl = curl_easy_init(); + if (!curl) { free(word); return NULL; } + + char *escaped = curl_easy_escape(curl, word, 0); + const char *base = "https://dictionary.cambridge.org/dictionary/english/"; + char *url = malloc(strlen(base) + strlen(escaped) + 1); + if (url) { + strcpy(url, base); + strcat(url, escaped); + } + + curl_free(escaped); + curl_easy_cleanup(curl); + free(word); + return url; } InfoBox fetch_dictionary_data(const char *query) { - InfoBox info = {NULL, NULL, NULL, NULL}; - - char *url = construct_dictionary_url(query); - if (!url) return info; - - CURL *curl = curl_easy_init(); - if (!curl) { free(url); return info; } - - struct MemStruct chunk = {malloc(1), 0}; - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0"); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - apply_proxy_settings(curl); - - if (curl_easy_perform(curl) == CURLE_OK && chunk.size > 0) { - htmlDocPtr doc = htmlReadMemory(chunk.memory, chunk.size, url, NULL, - HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); - if (doc) { - char *word = xpath_text(doc, "//span[@class='hw dhw']"); - char *pron = xpath_text(doc, "//span[@class='us dpron-i']//span[@class='ipa dipa lpr-2 lpl-1']"); - char *pos = xpath_text(doc, "//span[@class='pos dpos']"); - char *def = xpath_text(doc, "(//div[@class='def ddef_d db'])[1]"); - char *ex = xpath_text(doc, "(//span[@class='eg deg'])[1]"); - - if (word && def) { - info.title = strdup("Dictionary"); - info.extract = build_html(word, pron, pos, def, ex); - info.thumbnail_url = strdup("/static/dictionary.jpg"); - info.url = strdup(url); - } - - free(word); free(pron); free(pos); free(def); free(ex); - xmlFreeDoc(doc); - } + InfoBox info = {NULL, NULL, NULL, NULL}; + + char *url = construct_dictionary_url(query); + if (!url) return info; + + CURL *curl = curl_easy_init(); + if (!curl) { free(url); return info; } + + struct MemStruct chunk = {malloc(1), 0}; + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0"); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + apply_proxy_settings(curl); + + if (curl_easy_perform(curl) == CURLE_OK && chunk.size > 0) { + htmlDocPtr doc = htmlReadMemory(chunk.memory, chunk.size, url, NULL, + HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); + if (doc) { + char *word = xpath_text(doc, "//span[@class='hw dhw']"); + char *pron = xpath_text(doc, "//span[@class='us dpron-i']//span[@class='ipa dipa lpr-2 lpl-1']"); + char *pos = xpath_text(doc, "//span[@class='pos dpos']"); + char *def = xpath_text(doc, "(//div[@class='def ddef_d db'])[1]"); + char *ex = xpath_text(doc, "(//span[@class='eg deg'])[1]"); + + if (word && def) { + info.title = strdup("Dictionary"); + info.extract = build_html(word, pron, pos, def, ex); + info.thumbnail_url = strdup("/static/dictionary.jpg"); + info.url = strdup(url); + } + + free(word); free(pron); free(pos); free(def); free(ex); + xmlFreeDoc(doc); } + } - curl_easy_cleanup(curl); - free(chunk.memory); - free(url); - return info; + curl_easy_cleanup(curl); + free(chunk.memory); + free(url); + return info; } \ No newline at end of file diff --git a/src/Infobox/Infobox.c b/src/Infobox/Infobox.c index 5043c05..337b057 100644 --- a/src/Infobox/Infobox.c +++ b/src/Infobox/Infobox.c @@ -2,12 +2,12 @@ #include void free_infobox(InfoBox *info) { - if (info->title) - free(info->title); - if (info->thumbnail_url) - free(info->thumbnail_url); - if (info->extract) - free(info->extract); - if (info->url) - free(info->url); + if (info->title) + free(info->title); + if (info->thumbnail_url) + free(info->thumbnail_url); + if (info->extract) + free(info->extract); + if (info->url) + free(info->url); } diff --git a/src/Infobox/Infobox.h b/src/Infobox/Infobox.h index a052b80..ecb16b6 100644 --- a/src/Infobox/Infobox.h +++ b/src/Infobox/Infobox.h @@ -2,10 +2,10 @@ #define INFOBOX_H typedef struct { - char *title; - char *thumbnail_url; - char *extract; - char *url; + char *title; + char *thumbnail_url; + char *extract; + char *url; } InfoBox; void free_infobox(InfoBox *info); diff --git a/src/Infobox/UnitConversion.c b/src/Infobox/UnitConversion.c index 6a08b9c..933dd71 100644 --- a/src/Infobox/UnitConversion.c +++ b/src/Infobox/UnitConversion.c @@ -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'); - has_num = 1; - p++; + 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++; - 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++; - 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; - } + } + if (has_denom && denom > 0) { + value = value / denom; + } } while (*p == '\'' || *p == '"') { - double extra = 0.0; + 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 = 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++; - } + 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'; - } + !(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'; - } + 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'; - } + 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'; - } + if (is_one) { + buf[len-2] = '\0'; } else { - if (!is_one) { - buf[len] = 's'; - buf[len+1] = '\0'; - } + 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), - "
" - "
" - "%s %s = %s %s" - "
", - val_buf, from_name_buf, - res_buf, to_name_buf); + "
" + "
" + "%s %s = %s %s" + "
", + val_buf, from_name_buf, + res_buf, to_name_buf); snprintf(html + n, sizeof(html) - n, "
"); return html; } diff --git a/src/Infobox/Wikipedia.c b/src/Infobox/Wikipedia.c index dff26f6..09c13c6 100644 --- a/src/Infobox/Wikipedia.c +++ b/src/Infobox/Wikipedia.c @@ -23,32 +23,32 @@ static void shorten_summary(char **extract_ptr, int max_chars) { int end_pos = max_chars; for (int i = max_chars; i > (max_chars / 2); i--) { - if (text[i] == '.' || text[i] == '!' || text[i] == '?') { - end_pos = i + 1; - break; - } + if (text[i] == '.' || text[i] == '!' || text[i] == '?') { + end_pos = i + 1; + break; + } } char *new_text = (char *)malloc(end_pos + 4); if (new_text) { - strncpy(new_text, text, end_pos); - new_text[end_pos] = '\0'; - strcat(new_text, "..."); - free(*extract_ptr); - *extract_ptr = new_text; + strncpy(new_text, text, end_pos); + new_text[end_pos] = '\0'; + strcat(new_text, "..."); + free(*extract_ptr); + *extract_ptr = new_text; } } static size_t WikiWriteMemoryCallback(void *contents, size_t size, size_t nmemb, - void *userp) { + void *userp) { size_t realsize = size * nmemb; struct WikiMemoryStruct *mem = (struct WikiMemoryStruct *)userp; char *ptr = realloc(mem->memory, mem->size + realsize + 1); if (ptr == NULL) { - fprintf(stderr, "Not enough memory (realloc returned NULL)\n"); - return 0; + fprintf(stderr, "Not enough memory (realloc returned NULL)\n"); + return 0; } mem->memory = ptr; @@ -63,48 +63,48 @@ static void extract_wiki_info(xmlNode *node, InfoBox *info) { xmlNode *cur_node = NULL; for (cur_node = node; cur_node; cur_node = cur_node->next) { - if (cur_node->type == XML_ELEMENT_NODE) { - if (strcmp((const char *)cur_node->name, "page") == 0) { - xmlChar *title = xmlGetProp(cur_node, (const xmlChar *)"title"); - if (title) { - info->title = strdup((const char *)title); - - const char *base_article_url = "https://en.wikipedia.org/wiki/"; - char *formatted_title = strdup((const char *)title); - for (int i = 0; formatted_title[i]; i++) { - if (formatted_title[i] == ' ') formatted_title[i] = '_'; - } - - info->url = - malloc(strlen(base_article_url) + strlen(formatted_title) + 1); - if (info->url) { - strcpy(info->url, base_article_url); - strcat(info->url, formatted_title); - } - free(formatted_title); - xmlFree(title); - } + if (cur_node->type == XML_ELEMENT_NODE) { + if (strcmp((const char *)cur_node->name, "page") == 0) { + xmlChar *title = xmlGetProp(cur_node, (const xmlChar *)"title"); + if (title) { + info->title = strdup((const char *)title); + + const char *base_article_url = "https://en.wikipedia.org/wiki/"; + char *formatted_title = strdup((const char *)title); + for (int i = 0; formatted_title[i]; i++) { + if (formatted_title[i] == ' ') formatted_title[i] = '_'; } - if (strcmp((const char *)cur_node->name, "thumbnail") == 0) { - xmlChar *source = xmlGetProp(cur_node, (const xmlChar *)"source"); - if (source) { - info->thumbnail_url = strdup((const char *)source); - xmlFree(source); - } + info->url = + malloc(strlen(base_article_url) + strlen(formatted_title) + 1); + if (info->url) { + strcpy(info->url, base_article_url); + strcat(info->url, formatted_title); } + free(formatted_title); + xmlFree(title); + } + } + + if (strcmp((const char *)cur_node->name, "thumbnail") == 0) { + xmlChar *source = xmlGetProp(cur_node, (const xmlChar *)"source"); + if (source) { + info->thumbnail_url = strdup((const char *)source); + xmlFree(source); + } + } - if (strcmp((const char *)cur_node->name, "extract") == 0) { - xmlChar *content = xmlNodeGetContent(cur_node); - if (content) { - info->extract = strdup((const char *)content); + if (strcmp((const char *)cur_node->name, "extract") == 0) { + xmlChar *content = xmlNodeGetContent(cur_node); + if (content) { + info->extract = strdup((const char *)content); - shorten_summary(&(info->extract), 300); - xmlFree(content); - } - } + shorten_summary(&(info->extract), 300); + xmlFree(content); + } } - extract_wiki_info(cur_node->children, info); + } + extract_wiki_info(cur_node->children, info); } } @@ -120,27 +120,27 @@ InfoBox fetch_wiki_data(char *api_url) { curl_handle = curl_easy_init(); if (curl_handle) { - curl_easy_setopt(curl_handle, CURLOPT_URL, api_url); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, - WikiWriteMemoryCallback); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); - apply_proxy_settings(curl_handle); - - res = curl_easy_perform(curl_handle); - - if (res == CURLE_OK) { - xmlDocPtr doc = - xmlReadMemory(chunk.memory, chunk.size, "noname.xml", NULL, 0); - if (doc != NULL) { - xmlNode *root_element = xmlDocGetRootElement(doc); - extract_wiki_info(root_element, &info); - xmlFreeDoc(doc); - } + curl_easy_setopt(curl_handle, CURLOPT_URL, api_url); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, + WikiWriteMemoryCallback); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + apply_proxy_settings(curl_handle); + + res = curl_easy_perform(curl_handle); + + if (res == CURLE_OK) { + xmlDocPtr doc = + xmlReadMemory(chunk.memory, chunk.size, "noname.xml", NULL, 0); + if (doc != NULL) { + xmlNode *root_element = xmlDocGetRootElement(doc); + extract_wiki_info(root_element, &info); + xmlFreeDoc(doc); } + } - curl_easy_cleanup(curl_handle); - free(chunk.memory); + curl_easy_cleanup(curl_handle); + free(chunk.memory); } return info; @@ -152,14 +152,14 @@ char *construct_wiki_url(const char *search_term) { char *escaped_term = curl_easy_escape(curl, search_term, 0); const char *base = - "https://en.wikipedia.org/w/" - "api.php?action=query&prop=extracts|pageimages&exintro&" - "explaintext&pithumbsize=400&format=xml&origin=*&titles="; + "https://en.wikipedia.org/w/" + "api.php?action=query&prop=extracts|pageimages&exintro&" + "explaintext&pithumbsize=400&format=xml&origin=*&titles="; char *full_url = malloc(strlen(base) + strlen(escaped_term) + 1); if (full_url) { - strcpy(full_url, base); - strcat(full_url, escaped_term); + strcpy(full_url, base); + strcat(full_url, escaped_term); } curl_free(escaped_term); -- cgit v1.2.3