diff options
| author | Aldrik Ramaekers <aldrikboy@gmail.com> | 2025-10-05 15:15:55 +0200 |
|---|---|---|
| committer | Aldrik Ramaekers <aldrikboy@gmail.com> | 2025-10-05 15:15:55 +0200 |
| commit | b278d242d03ba614779243ec9e9495fc95abea3d (patch) | |
| tree | 0d3cd94a3a059b0754c61da075c7dcecc081f358 | |
| parent | 0a2b0e347d926ac0f29c9dd0f49e00634e822d0e (diff) | |
strops format
| -rw-r--r-- | include/administration.hpp | 2 | ||||
| -rw-r--r-- | include/importer.hpp | 6 | ||||
| -rw-r--r-- | include/strops.hpp | 5 | ||||
| -rw-r--r-- | src/administration.cpp | 25 | ||||
| -rw-r--r-- | src/administration_reader.cpp | 1 | ||||
| -rw-r--r-- | src/administration_writer.cpp | 14 | ||||
| -rw-r--r-- | src/ai_providers/DeepSeek.cpp | 3 | ||||
| -rw-r--r-- | src/ai_providers/openAI.cpp | 15 | ||||
| -rw-r--r-- | src/importer.cpp | 8 | ||||
| -rw-r--r-- | src/logger.cpp | 9 | ||||
| -rw-r--r-- | src/strops.cpp | 44 | ||||
| -rw-r--r-- | src/ui/imgui_extensions.cpp | 19 | ||||
| -rw-r--r-- | src/ui/ui_contacts.cpp | 9 | ||||
| -rw-r--r-- | src/ui/ui_earnings.cpp | 1 | ||||
| -rw-r--r-- | src/ui/ui_expenses.cpp | 6 | ||||
| -rw-r--r-- | src/ui/ui_invoices.cpp | 6 | ||||
| -rw-r--r-- | src/ui/ui_projects.cpp | 7 | ||||
| -rw-r--r-- | src/ui/ui_settings.cpp | 21 | ||||
| -rw-r--r-- | tests/test_helper.cpp | 3 |
19 files changed, 111 insertions, 93 deletions
diff --git a/include/administration.hpp b/include/administration.hpp index 4cd83ee..75f5b52 100644 --- a/include/administration.hpp +++ b/include/administration.hpp @@ -341,6 +341,8 @@ typedef enum { AI_PROVIDER_OPENAI = 0, AI_PROVIDER_DEEPSEEK = 1, + + AI_PROVIDER_END, } ai_provider; typedef struct diff --git a/include/importer.hpp b/include/importer.hpp index fde297a..cb24cf8 100644 --- a/include/importer.hpp +++ b/include/importer.hpp @@ -23,9 +23,10 @@ #define I_ERR_FAILED_QUERY 2 #define I_ERR_FAILED_IMPORT 3 +typedef uint32_t i_err; + namespace importer { - typedef uint32_t i_err; typedef enum { @@ -47,6 +48,7 @@ namespace importer { typedef struct { + char* provider_name; bool (*upload_file)(char* file_path, char* file_id, size_t file_id_len); bool (*query_with_file)(char* query, size_t query_length, char* file_id, char** response); } ai_provider_impl; @@ -55,5 +57,5 @@ namespace importer { const char* status_to_string(status status); invoice_request* ai_document_to_invoice(char* file_path); - + ai_provider_impl get_ai_provider_implementation(ai_provider provider); }
\ No newline at end of file diff --git a/include/strops.hpp b/include/strops.hpp index 3a85543..5dc7368 100644 --- a/include/strops.hpp +++ b/include/strops.hpp @@ -23,10 +23,15 @@ namespace strops { size_t copy(char *dst, const char *src, size_t size); char* contains(char* a, char* b); bool equals(const char* a, const char* b); + + s32 format_va(char* s, size_t n, const char* format, va_list args); + s32 format(char* s, size_t n, const char* format, ...); + void replace(char *buf, size_t buf_size, const char *search, const char *replace); void replace_int32(char *buf, size_t buf_size, const char *search, s32 number); void replace_int64(char *buf, size_t buf_size, const char *search, s64 number); void replace_float(char *buf, size_t buf_size, const char *search, float number, int decimals); + bool is_prefixed(const char *pre, const char *str); char* get_filename(const char* path); diff --git a/src/administration.cpp b/src/administration.cpp index 1de99b4..a3d3c2f 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -16,7 +16,6 @@ #define _CRT_SECURE_NO_WARNINGS -#include <string.h> #include <stdlib.h> #include <assert.h> #include <time.h> @@ -61,7 +60,7 @@ static void create_default_tax_rates() #define ADD_BRACKET(_country, _rate, _code)\ {\ tax_rate* tb = (tax_rate*)malloc(sizeof(tax_rate));\ - snprintf(tb->id, sizeof(tb->id), "T/%d", create_id());\ + strops::format(tb->id, sizeof(tb->id), "T/%d", create_id());\ memcpy(tb->country_code, _country, sizeof(tb->country_code));\ tb->rate = _rate;\ memcpy(tb->category_code, _code, sizeof(tb->category_code));\ @@ -224,7 +223,7 @@ static void create_default_cost_centers() #define ADD_COSTCENTER(_description, _code)\ {\ cost_center* tb = (cost_center*)malloc(sizeof(cost_center));\ - snprintf(tb->id, sizeof(tb->id), "E/%d", create_id());\ + strops::format(tb->id, sizeof(tb->id), "E/%d", create_id());\ memcpy(tb->description, _description, sizeof(tb->description));\ memcpy(tb->code, _code, sizeof(tb->code));\ list_append(&g_administration.cost_centers, tb);\ @@ -529,7 +528,7 @@ void administration::create_income_statement(income_statement* statement) quarter.report_count = 0; quarter.is_empty = 1; quarter.profit = 0.0f; - snprintf(quarter.quarter_str, MAX_LEN_SHORT_DESC, "%dQ%d", quarter.quarter+1, quarter.year); + strops::format(quarter.quarter_str, MAX_LEN_SHORT_DESC, "%dQ%d", quarter.quarter+1, quarter.year); project_count = administration::project_count(); project* project_buffer = (project*)malloc(sizeof(project)*project_count); @@ -913,7 +912,7 @@ contact administration::contact_create_empty() { contact result; memset(&result, 0, sizeof(contact)); - snprintf(result.id, sizeof(result.id), "C/%d", create_id()); + strops::format(result.id, sizeof(result.id), "C/%d", create_id()); return result; } @@ -1100,7 +1099,7 @@ project administration::project_create_empty() result.start_date = time(NULL); result.start_date -= (result.start_date % 86400); result.end_date = 0; - snprintf(result.id, sizeof(result.id), "P/%d", create_id()); + strops::format(result.id, sizeof(result.id), "P/%d", create_id()); return result; } @@ -1111,8 +1110,8 @@ tax_rate administration::tax_rate_create_empty() { tax_rate result; memset(&result, 0, sizeof(tax_rate)); - snprintf(result.id, sizeof(result.id), "T/%d", create_id()); - snprintf(result.category_code, sizeof(result.category_code), "S"); // S = standard rate. + strops::format(result.id, sizeof(result.id), "T/%d", create_id()); + strops::format(result.category_code, sizeof(result.category_code), "S"); // S = standard rate. return result; } @@ -1125,7 +1124,7 @@ a_err administration::tax_rate_get_by_shorthandle(tax_rate* buffer, char* handle tax_rate c = *(tax_rate *)list_iterator_next(&g_administration.tax_rates); char compare_str[20]; - snprintf(compare_str, 20, "%s/%.2f", c.country_code, c.rate); + strops::format(compare_str, 20, "%s/%.2f", c.country_code, c.rate); if (strcmp(compare_str, handle) == 0) { *buffer = c; @@ -1273,7 +1272,7 @@ cost_center administration::cost_center_create_empty() { cost_center cc; memset(&cc, 0, sizeof(cost_center)); - snprintf(cc.id, sizeof(cc.id), "E/%d", create_id()); + strops::format(cc.id, sizeof(cc.id), "E/%d", create_id()); return cc; } @@ -1447,8 +1446,8 @@ invoice administration::invoice_create_empty() { invoice result; memset(&result, 0, sizeof(invoice)); - snprintf(result.id, sizeof(result.id), "I/%d", create_id()); - snprintf(result.sequential_number, sizeof(result.id), "INV%010d", create_sequence_number()); + strops::format(result.id, sizeof(result.id), "I/%d", create_id()); + strops::format(result.sequential_number, sizeof(result.id), "INV%010d", create_sequence_number()); result.issued_at = time(NULL); result.issued_at -= (result.issued_at % 86400); @@ -1951,7 +1950,7 @@ a_err administration::billing_item_add_to_invoice(invoice* invoice, billing_item if (!tb) return A_ERR_GENERIC; memcpy(tb, &item, sizeof(billing_item)); - snprintf(tb->id, sizeof(tb->id), "B/%d", create_id()); + strops::format(tb->id, sizeof(tb->id), "B/%d", create_id()); strops::copy(tb->currency, invoice->currency, MAX_LEN_CURRENCY); // Set billing item currency to invoice currency. administration_recalculate_billing_item_totals(tb); diff --git a/src/administration_reader.cpp b/src/administration_reader.cpp index 7400caf..e39ae8c 100644 --- a/src/administration_reader.cpp +++ b/src/administration_reader.cpp @@ -16,7 +16,6 @@ #include <malloc.h> #include <stdio.h> -#include <stdlib.h> #include <stdint.h> #include <zip.h> #include <xml.h> diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp index b6dbb8c..040b842 100644 --- a/src/administration_writer.cpp +++ b/src/administration_writer.cpp @@ -131,7 +131,7 @@ static bool delete_entry_by_name(char* entry) bool administration_writer::delete_entry(char* id) { char final_path[50]; - snprintf(final_path, 50, "%s.xml", id); + strops::format(final_path, 50, "%s.xml", id); return delete_entry_by_name(final_path); } @@ -299,7 +299,7 @@ static void _add_document_to_zip(invoice* inv) if (strlen(doc->copy_path) == 0 && strlen(doc->original_path) != 0) { char copy_path[MAX_LEN_PATH]; - snprintf(copy_path, MAX_LEN_PATH, "documents/%s%s", inv->sequential_number, _get_file_extension(doc->original_path)); + strops::format(copy_path, MAX_LEN_PATH, "documents/%s%s", inv->sequential_number, _get_file_extension(doc->original_path)); FILE* orig_file = fopen(doc->original_path, "rb"); if (orig_file == NULL) { @@ -517,7 +517,7 @@ bool administration_writer::save_invoice_blocking(invoice inv) //// Write to Disk. char final_path[50]; - snprintf(final_path, 50, "%s.xml", inv.id); + strops::format(final_path, 50, "%s.xml", inv.id); int final_length = (int)strlen(file_content); if (!xml_parse_document((uint8_t*)file_content, final_length)) result = 0; @@ -576,7 +576,7 @@ bool administration_writer::save_project_blocking(project project) //// Write to Disk. char final_path[50]; - snprintf(final_path, 50, "%s.xml", project.id); + strops::format(final_path, 50, "%s.xml", project.id); int final_length = (int)strlen(file_content); if (!xml_parse_document((uint8_t*)file_content, final_length)) result = 0; @@ -624,7 +624,7 @@ bool administration_writer::save_cost_center_blocking(cost_center cost) //// Write to Disk. char final_path[50]; - snprintf(final_path, 50, "%s.xml", cost.id); + strops::format(final_path, 50, "%s.xml", cost.id); int final_length = (int)strlen(file_content); if (!xml_parse_document((uint8_t*)file_content, final_length)) result = 0; @@ -673,7 +673,7 @@ bool administration_writer::save_tax_rate_blocking(tax_rate rate) //// Write to Disk. char final_path[50]; - snprintf(final_path, 50, "%s.xml", rate.id); + strops::format(final_path, 50, "%s.xml", rate.id); int final_length = (int)strlen(file_content); if (!xml_parse_document((uint8_t*)file_content, final_length)) result = 0; @@ -733,7 +733,7 @@ bool administration_writer::save_contact_blocking(contact c) strops::replace(file_content, buf_length, "{{CONTACT_REGION}}", c.address.region); char final_path[50]; - snprintf(final_path, 50, "%s.xml", c.id); + strops::format(final_path, 50, "%s.xml", c.id); int final_length = (int)strlen(file_content); if (!xml_parse_document((uint8_t*)file_content, final_length)) result = 0; diff --git a/src/ai_providers/DeepSeek.cpp b/src/ai_providers/DeepSeek.cpp index 5a378dd..4dd4e0a 100644 --- a/src/ai_providers/DeepSeek.cpp +++ b/src/ai_providers/DeepSeek.cpp @@ -50,7 +50,7 @@ static bool _DeepSeek_query_with_file(char* query, size_t query_length, char* fi size_t body_size = file_size + QUERY_BUFFER_SIZE; char* body = (char*)malloc(body_size); - snprintf(body, body_size, + strops::format(body, body_size, "{\"model\":\"deepseek-reasoner\", \"messages\": [ { \"role\": \"user\", \"content\": \"%s\" } ] }", query_escaped); httplib::Headers headers; @@ -117,6 +117,7 @@ static bool _DeepSeek_upload_file(char* file_path, char* file_id, size_t file_id } importer::ai_provider_impl _deepseek_api_provider = { + "DeekSeek", _DeepSeek_upload_file, _DeepSeek_query_with_file, };
\ No newline at end of file diff --git a/src/ai_providers/openAI.cpp b/src/ai_providers/openAI.cpp index bbe9f8f..c4526ef 100644 --- a/src/ai_providers/openAI.cpp +++ b/src/ai_providers/openAI.cpp @@ -39,7 +39,7 @@ static bool _openAI_query_with_file(char* query, size_t query_length, char* file size_t body_size = query_length + 200; char* body = (char*)malloc(body_size); - snprintf(body, body_size, + strops::format(body, body_size, "{\"model\":\"gpt-5-nano\", \"input\": [ { \"role\": \"user\", \"content\": [ { \"type\": \"input_file\", \"file_id\": \"%s\" }, " "{ \"type\": \"input_text\", \"text\": \"%s\" } ] } ] }", file_id, query_escaped); @@ -90,7 +90,7 @@ static bool _openAI_upload_file(char* file_path, char* file_id, size_t file_id_l //cli.enable_server_certificate_verification(false); char body[512]; - snprintf(body, sizeof(body), "{\"filename\":\"%s\",\"purpose\":\"user_data\", \"bytes\": %d, \"mime_type\": \"application/pdf\", \"expires_after\": { \"anchor\": \"created_at\", \"seconds\": 3600 } }", filename, sz); + strops::format(body, sizeof(body), "{\"filename\":\"%s\",\"purpose\":\"user_data\", \"bytes\": %d, \"mime_type\": \"application/pdf\", \"expires_after\": { \"anchor\": \"created_at\", \"seconds\": 3600 } }", filename, sz); httplib::Headers headers; headers.insert(std::make_pair("Authorization", std::string("Bearer ") + api_key)); @@ -111,7 +111,7 @@ static bool _openAI_upload_file(char* file_path, char* file_id, size_t file_id_l char *buffer = (char*)malloc(part_size); char completion_body[1048]; - snprintf(completion_body, sizeof(completion_body), "{\"part_ids\": ["); + strops::format(completion_body, sizeof(completion_body), "{\"part_ids\": ["); int part_number = 0; while (1) { @@ -128,7 +128,7 @@ static bool _openAI_upload_file(char* file_path, char* file_id, size_t file_id_l }; char path[256]; - snprintf(path, sizeof(path), "/v1/uploads/%s/parts?part_number=%d", upload_id, part_number); + strops::format(path, sizeof(path), "/v1/uploads/%s/parts?part_number=%d", upload_id, part_number); httplib::Result part_res = cli.Post(path, part_headers, items); @@ -142,15 +142,15 @@ static bool _openAI_upload_file(char* file_path, char* file_id, size_t file_id_l else { char part_id[128]; strops::get_json_value(part_res->body.c_str(), "id", part_id, sizeof(part_id)); - if (part_number == 0) snprintf(completion_body+strlen(completion_body), sizeof(completion_body)-strlen(completion_body), "\"%s\"", part_id); - if (part_number != 0) snprintf(completion_body+strlen(completion_body), sizeof(completion_body)-strlen(completion_body), ", \"%s\"", part_id); + if (part_number == 0) strops::format(completion_body+strlen(completion_body), sizeof(completion_body)-strlen(completion_body), "\"%s\"", part_id); + if (part_number != 0) strops::format(completion_body+strlen(completion_body), sizeof(completion_body)-strlen(completion_body), ", \"%s\"", part_id); } logger::info("Uploaded part %d\n", part_number); part_number++; } - snprintf(completion_body+strlen(completion_body), sizeof(completion_body)-strlen(completion_body), "]}"); + strops::format(completion_body+strlen(completion_body), sizeof(completion_body)-strlen(completion_body), "]}"); free(buffer); fclose(orig_file); @@ -174,6 +174,7 @@ static bool _openAI_upload_file(char* file_path, char* file_id, size_t file_id_l } importer::ai_provider_impl _chatgpt_api_provider = { + "OpenAI", _openAI_upload_file, _openAI_query_with_file, };
\ No newline at end of file diff --git a/src/importer.cpp b/src/importer.cpp index 3f81672..8b5cc5c 100644 --- a/src/importer.cpp +++ b/src/importer.cpp @@ -33,10 +33,8 @@ extern importer::ai_provider_impl _chatgpt_api_provider; extern importer::ai_provider_impl _deepseek_api_provider; -importer::ai_provider_impl _ai_get_impl() +importer::ai_provider_impl importer::get_ai_provider_implementation(ai_provider provider) { - ai_provider provider = administration::get_ai_service().provider; - switch(provider) { case AI_PROVIDER_OPENAI: return _chatgpt_api_provider; @@ -50,7 +48,7 @@ importer::ai_provider_impl _ai_get_impl() static int _ai_document_to_invoice_t(void *arg) { importer::invoice_request* request = (importer::invoice_request*)arg; char* file_path = request->file_path; - importer::ai_provider_impl impl = _ai_get_impl(); + importer::ai_provider_impl impl = importer::get_ai_provider_implementation(administration::get_ai_service().provider); request->status = importer::status::IMPORT_UPLOADING_FILE; @@ -179,7 +177,7 @@ const char* importer::status_to_string(importer::status status) return ""; } -const char* importer::error_to_string(importer::i_err error) +const char* importer::error_to_string(i_err error) { switch(error) { diff --git a/src/logger.cpp b/src/logger.cpp index 38d17b7..df0ae91 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -17,7 +17,10 @@ #include <stdio.h> #include <stdarg.h> #include <time.h> + #include "timer.h" + +#include "strops.hpp" #include "logger.hpp" namespace logger { @@ -26,7 +29,7 @@ namespace logger { static void log_message(const char* fmt, ImVec4 color, va_list args) { - vsnprintf(g_log.history[g_log.write_cursor], logger::MAX_LEN_LOG_TXT, fmt, args); + strops::format_va(g_log.history[g_log.write_cursor], logger::MAX_LEN_LOG_TXT, fmt, args); g_log.colors[g_log.write_cursor] = color; tick_t ms_since_epoch = timer_system(); @@ -42,14 +45,14 @@ namespace logger { localtime_r(&seconds, &tm_time); #endif - snprintf(time_buf, 50, "%02d:%02d %02d.%03d", + strops::format(time_buf, 50, "%02d:%02d %02d.%03d", tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, milliseconds); char tmp[logger::MAX_LEN_LOG_TXT]; - snprintf(tmp, logger::MAX_LEN_LOG_TXT, "[%s] %s", time_buf, g_log.history[g_log.write_cursor]); + strops::format(tmp, logger::MAX_LEN_LOG_TXT, "[%s] %s", time_buf, g_log.history[g_log.write_cursor]); tmp[logger::MAX_LEN_LOG_TXT-1] = 0; memcpy(g_log.history[g_log.write_cursor], tmp, logger::MAX_LEN_LOG_TXT); diff --git a/src/strops.cpp b/src/strops.cpp index 356ce5b..6142c01 100644 --- a/src/strops.cpp +++ b/src/strops.cpp @@ -15,7 +15,6 @@ */ #include <stdlib.h> -#include <string.h> #include <ctype.h> #include <stdio.h> @@ -51,17 +50,32 @@ namespace strops { char* contains(char* haystack, char* needle) { do { - const char* h = haystack; - const char* n = needle; - while (tolower((unsigned char) *h) == tolower((unsigned char ) *n) && *n) { - h++; - n++; - } - if (*n == 0) { - return (char *) haystack; + const char* h = haystack; + const char* n = needle; + while (tolower((unsigned char) *h) == tolower((unsigned char ) *n) && *n) { + h++; + n++; + } + if (*n == 0) { + return (char *) haystack; } - } while (*haystack++); - return 0; + } while (*haystack++); + return 0; + } + + s32 format_va(char* s, size_t n, const char* format, va_list args) + { + s32 result = vsnprintf(s, n, format, args); + return result; + } + + s32 format(char* s, size_t n, const char* format, ...) + { + va_list args; + va_start (args, format); + s32 result = vsnprintf(s, n, format, args); + va_end (args); + return result; } void replace(char *buf, size_t buf_size, const char *search, const char *replace) @@ -99,28 +113,28 @@ namespace strops { void replace_int32(char *buf, size_t buf_size, const char *search, s32 number) { char num_buf[200]; - snprintf(num_buf, 200, "%d", number); + strops::format(num_buf, 200, "%d", number); strops::replace(buf, buf_size, search, num_buf); } void replace_int64(char *buf, size_t buf_size, const char *search, s64 number) { char num_buf[200]; - snprintf(num_buf, 200, "%lld", number); + strops::format(num_buf, 200, "%lld", number); strops::replace(buf, buf_size, search, num_buf); } void replace_float(char *buf, size_t buf_size, const char *search, float number, int decimals) { char num_buf[200]; - snprintf(num_buf, 200, "%.*f", decimals, number); + strops::format(num_buf, 200, "%.*f", decimals, number); strops::replace(buf, buf_size, search, num_buf); } char* get_json_value(const char *json, const char *key, char *out, size_t out_size, int skip) { char pattern[128]; - snprintf(pattern, sizeof(pattern), "\"%s\"", key); + strops::format(pattern, sizeof(pattern), "\"%s\"", key); const char *pos = strstr(json, pattern); while(skip > 0) { pos = strstr(pos+1, pattern); diff --git a/src/ui/imgui_extensions.cpp b/src/ui/imgui_extensions.cpp index 5a00648..4e8270a 100644 --- a/src/ui/imgui_extensions.cpp +++ b/src/ui/imgui_extensions.cpp @@ -1,4 +1,3 @@ -#include <stdio.h> #include <stdlib.h> #include "ui.hpp" @@ -93,7 +92,7 @@ namespace ImGui for (int x = 0; x < config::country_count; x++) { char locale_str[20]; - snprintf(locale_str, 20, "country.%s", config::country_codes[x]); + strops::format(locale_str, 20, "country.%s", config::country_codes[x]); countries[x] = locale::get(locale_str); } @@ -227,7 +226,7 @@ namespace ImGui for (int i = 0; i < autocomplete_count; i++) { autocomplete_strings[i] = (char*)malloc(200); - snprintf(autocomplete_strings[i], 200, "%s (%s %s)", autocomplete_list[i].name, autocomplete_list[i].address.address1, autocomplete_list[i].address.address2); + strops::format(autocomplete_strings[i], 200, "%s (%s %s)", autocomplete_list[i].name, autocomplete_list[i].address.address1, autocomplete_list[i].address.address2); } int autocomplete_index = ImGui::TextInputWithAutocomplete(locale::get("contact.form.fullname"), @@ -355,10 +354,10 @@ namespace ImGui { if (strcmp(selected_tax_rate->country_code, "00") == 0) { char category_code_desc[MAX_LEN_LONG_DESC]; - snprintf(category_code_desc, MAX_LEN_LONG_DESC, "taxcategory.%s", selected_tax_rate->category_code); - snprintf(rate_str_buf, 40, "%s", locale::get(category_code_desc)); + strops::format(category_code_desc, MAX_LEN_LONG_DESC, "taxcategory.%s", selected_tax_rate->category_code); + strops::format(rate_str_buf, 40, "%s", locale::get(category_code_desc)); } - else snprintf(rate_str_buf, 40, "%s/%.1f%%", selected_tax_rate->country_code, selected_tax_rate->rate); + else strops::format(rate_str_buf, 40, "%s/%.1f%%", selected_tax_rate->country_code, selected_tax_rate->rate); } if (has_error) { @@ -374,10 +373,10 @@ namespace ImGui if (strcmp(buffer[n].country_code, "00") == 0) { char category_code_desc[MAX_LEN_LONG_DESC]; - snprintf(category_code_desc, MAX_LEN_LONG_DESC, "taxcategory.%s", buffer[n].category_code); - snprintf(rate_str_buf, 40, "%s", locale::get(category_code_desc)); + strops::format(category_code_desc, MAX_LEN_LONG_DESC, "taxcategory.%s", buffer[n].category_code); + strops::format(rate_str_buf, 40, "%s", locale::get(category_code_desc)); } - else snprintf(rate_str_buf, 40, "%s/%.1f%%", buffer[n].country_code, buffer[n].rate); + else strops::format(rate_str_buf, 40, "%s/%.1f%%", buffer[n].country_code, buffer[n].rate); if (ImGui::Selectable(rate_str_buf, is_selected)) { selected_tax_rate_index = n; @@ -458,7 +457,7 @@ namespace ImGui const char* items[] = { option1, option2 }; char ID[MAX_LEN_LONG_DESC]; - snprintf(ID, MAX_LEN_LONG_DESC, "Mode##%p", buffer); + strops::format(ID, MAX_LEN_LONG_DESC, "Mode##%p", buffer); if (ImGui::BeginCombo(ID, items[*buffer])) { for (int n = 0; n < 2; n++) { bool is_selected = (n == (int)*buffer); diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp index 03fcee0..7d585c9 100644 --- a/src/ui/ui_contacts.cpp +++ b/src/ui/ui_contacts.cpp @@ -14,9 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdio.h> -#include <stdlib.h> - #include "strops.hpp" #include "config.hpp" #include "ui.hpp" @@ -163,7 +160,7 @@ static void draw_contact_list() ImGui::TableSetColumnIndex(3); char btn_name[20]; - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); if (ImGui::Button(btn_name)) { active_contact = c; current_view_state = ui::view_state::VIEW_EXISTING; @@ -171,14 +168,14 @@ static void draw_contact_list() ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); if (ImGui::Button(btn_name)) { active_contact = c; current_view_state = ui::view_state::EDIT_EXISTING; } ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); if (ImGui::Button(btn_name)) { selected_for_removal = c; ImGui::OpenPopup("ConfirmDeletePopup"); diff --git a/src/ui/ui_earnings.cpp b/src/ui/ui_earnings.cpp index 5e04a61..1ceabbe 100644 --- a/src/ui/ui_earnings.cpp +++ b/src/ui/ui_earnings.cpp @@ -14,7 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <stdio.h> #include <stdlib.h> #include "ui.hpp" diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp index e4441ef..8812273 100644 --- a/src/ui/ui_expenses.cpp +++ b/src/ui/ui_expenses.cpp @@ -244,7 +244,7 @@ static void draw_expenses_list() ImGui::TableSetColumnIndex(6); char btn_name[20]; - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); if (ImGui::Button(btn_name)) { active_invoice = c; current_view_state = ui::view_state::VIEW_EXISTING; @@ -252,14 +252,14 @@ static void draw_expenses_list() ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); if (ImGui::Button(btn_name)) { active_invoice = administration::invoice_create_copy(&c); // We create a copy because of billing item list pointers. current_view_state = ui::view_state::EDIT_EXISTING; } ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); if (ImGui::Button(btn_name)) { selected_for_removal = c; ImGui::OpenPopup("ConfirmDeletePopup"); diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index 191cd7d..4dd44e8 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -341,7 +341,7 @@ static void draw_invoices_list() ImGui::TableSetColumnIndex(6); char btn_name[20]; - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); if (ImGui::Button(btn_name)) { active_invoice = c; current_view_state = ui::view_state::VIEW_EXISTING; @@ -351,14 +351,14 @@ static void draw_invoices_list() if (c.status == invoice_status::INVOICE_CONCEPT) { - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); if (ImGui::Button(btn_name)) { active_invoice = administration::invoice_create_copy(&c); // We create a copy because of billing item list pointers. current_view_state = ui::view_state::EDIT_EXISTING; } ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); if (ImGui::Button(btn_name)) { selected_for_removal = c; ImGui::OpenPopup("ConfirmDeletePopup"); diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp index f9f494d..66cc336 100644 --- a/src/ui/ui_projects.cpp +++ b/src/ui/ui_projects.cpp @@ -21,6 +21,7 @@ #include "administration.hpp" #include "administration_writer.hpp" #include "locales.hpp" +#include "strops.hpp" static ui::view_state current_view_state = ui::view_state::LIST_ALL; static project selected_for_cancellation; @@ -139,7 +140,7 @@ static void draw_project_list() ImGui::TableSetColumnIndex(3); char btn_name[20]; - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); if (ImGui::Button(btn_name)) { active_project = c; current_view_state = ui::view_state::VIEW_EXISTING; @@ -148,14 +149,14 @@ static void draw_project_list() if (c.state == project_state::PROJECT_RUNNING) { ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); if (ImGui::Button(btn_name)) { active_project = c; current_view_state = ui::view_state::EDIT_EXISTING; } ImGui::SameLine(); - snprintf(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.cancel"), i); + strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.cancel"), i); if (ImGui::Button(btn_name)) { selected_for_cancellation = c; ImGui::OpenPopup("ConfirmCancelProject"); diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp index cb6cdf5..8177f07 100644 --- a/src/ui/ui_settings.cpp +++ b/src/ui/ui_settings.cpp @@ -15,13 +15,13 @@ */ #include <stdlib.h> -#include <stdio.h> #include "strops.hpp" #include "ui.hpp" #include "imgui.h" #include "administration.hpp" #include "locales.hpp" +#include "importer.hpp" #include "administration_writer.hpp" extern void draw_contact_form(contact* buffer, bool viewing_only = false); @@ -103,7 +103,7 @@ static void draw_vat_rates() ImGui::TableNextRow(); char locale_buf[20]; - snprintf(locale_buf, sizeof(locale_buf), "country.%s", c.country_code); + strops::format(locale_buf, sizeof(locale_buf), "country.%s", c.country_code); ImGui::TableSetColumnIndex(0); ImGui::Text(locale::get(locale_buf)); @@ -112,7 +112,7 @@ static void draw_vat_rates() { ImGui::SameLine(); char btn_name[20]; - snprintf(btn_name, sizeof(btn_name), "+##%d",i); + strops::format(btn_name, sizeof(btn_name), "+##%d",i); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); if (ImGui::Button(btn_name, ImVec2(20,20))) { is_adding_item = true; @@ -131,7 +131,7 @@ static void draw_vat_rates() ImGui::TableSetColumnIndex(0); char category_code_desc[MAX_LEN_LONG_DESC]; - snprintf(category_code_desc, MAX_LEN_LONG_DESC, "taxcategory.%s", c.category_code); + strops::format(category_code_desc, MAX_LEN_LONG_DESC, "taxcategory.%s", c.category_code); ImGui::Text(can_be_modified ? "" : locale::get(category_code_desc)); @@ -338,18 +338,17 @@ static void draw_services() // AI service if (ImGui::CollapsingHeader(locale::get("settings.services.ai_service"))) { - // TODO: get this from iterator over ai_get_impl - char* services[2] = { - "OpenAI", - "DeepSeek", - }; + char* ai_service_names[AI_PROVIDER_END]; + for (u32 i = 0; i < AI_PROVIDER_END; i++) { + ai_service_names[i] = importer::get_ai_provider_implementation((ai_provider)i).provider_name; + } - if (ImGui::BeginCombo(locale::get("settings.services.ai_service.provider"), services[new_service.provider])) + if (ImGui::BeginCombo(locale::get("settings.services.ai_service.provider"), ai_service_names[new_service.provider])) { for (u32 n = 0; n < 2; n++) { bool is_selected = n == (uint32_t)new_service.provider; - if (ImGui::Selectable(services[n], is_selected)) { + if (ImGui::Selectable(ai_service_names[n], is_selected)) { new_service.provider = (ai_provider)n; } } diff --git a/tests/test_helper.cpp b/tests/test_helper.cpp index f0b0d66..b74916a 100644 --- a/tests/test_helper.cpp +++ b/tests/test_helper.cpp @@ -1,6 +1,5 @@ #define _CRT_SECURE_NO_WARNINGS -#include <stdio.h> #include <stdlib.h> #include <malloc.h> @@ -174,7 +173,7 @@ static bool _test_peppol_file(char* id) zip_extract(test_file_path, extract_dir, 0, 0); char command[200]; - snprintf(command, 200, "java -jar libs\\schxslt-cli.jar -d %s\\%s.xml -s %s -o %s > NUL 2>&1", + strops::format(command, 200, "java -jar libs\\schxslt-cli.jar -d %s\\%s.xml -s %s -o %s > NUL 2>&1", extract_dir, id, validation_file, result_file); system(command); |
