diff options
Diffstat (limited to 'src/currency.c')
-rw-r--r-- | src/currency.c | 414 |
1 files changed, 223 insertions, 191 deletions
diff --git a/src/currency.c b/src/currency.c index 4029763..2add81b 100644 --- a/src/currency.c +++ b/src/currency.c @@ -11,234 +11,266 @@ #include "mp.h" typedef struct { - char *short_name; - MPNumber value; + char* short_name; + MPNumber value; } currency; -static currency *currencies = NULL; +static currency* currencies = NULL; static int currency_count = 0; static gboolean downloading_rates = FALSE; static gboolean loaded_rates = FALSE; -static char* -get_rate_filepath() +static char* get_rate_filepath() { - return g_build_filename(g_get_user_cache_dir (), - "mate-calc", - "eurofxref-daily.xml", - NULL); + return g_build_filename(g_get_user_cache_dir(), "mate-calc", "eurofxref-daily.xml", NULL); } -static int -currency_get_index(const char *short_name) +static int currency_get_index(const char *short_name) { - int i; - for (i = 0; i < currency_count; i++) { - if (!strcmp(short_name, currencies[i].short_name)) { - if (mp_is_negative(¤cies[i].value) || - mp_is_zero(¤cies[i].value)) { - return -1; - } else { - return i; - } - } - } - return -1; + int i; + + for (i = 0; i < currency_count; i++) + { + if (!strcmp(short_name, currencies[i].short_name)) + { + if (mp_is_negative(¤cies[i].value) || mp_is_zero(¤cies[i].value)) + { + return -1; + } + else + { + return i; + } + } + } + + return -1; } /* A file needs to be redownloaded if it doesn't exist, or every 7 days. * When an error occur, it probably won't hurt to try to download again. */ -static int -currency_rates_needs_update() +static int currency_rates_needs_update() { - gchar *filename = get_rate_filepath (); - struct stat buf; - if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { - g_free(filename); - return 1; - } - - if (g_stat(filename, &buf) == -1) { - g_free(filename); - return 1; - } - g_free(filename); - - if (difftime(time(NULL), buf.st_mtime) > (60 * 60 * 24 * 7)) { - return 1; - } - - return 0; -} + gchar* filename = get_rate_filepath(); + struct stat buf; + if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + { + g_free(filename); + return 1; + } -static void -download_cb(GObject *object, GAsyncResult *result, gpointer user_data) -{ - GError *error = NULL; - - if (g_file_copy_finish(G_FILE(object), result, &error)) - g_debug("Rates updated"); - else - g_warning("Couldn't download currency file: %s", error->message); - g_clear_error(&error); - downloading_rates = FALSE; -} + if (g_stat(filename, &buf) == -1) + { + g_free(filename); + return 1; + } + g_free(filename); -static void -currency_download_rates() -{ - gchar *filename, *directory; - GFile *source, *dest; + if (difftime(time(NULL), buf.st_mtime) > (60 * 60 * 24 * 7)) + { + return 1; + } + + return 0; +} - downloading_rates = TRUE; - g_debug("Downloading rates..."); - filename = get_rate_filepath(); - directory = g_path_get_dirname(filename); - g_mkdir_with_parents(directory, 0755); - g_free(directory); +static void download_cb(GObject* object, GAsyncResult* result, gpointer user_data) +{ + GError* error = NULL; + + if (g_file_copy_finish(G_FILE(object), result, &error)) + { + g_debug("Rates updated"); + } + else + { + g_warning("Couldn't download currency file: %s", error->message); + } + + g_clear_error(&error); + downloading_rates = FALSE; +} - source = g_file_new_for_uri ("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"); - dest = g_file_new_for_path (filename); - g_free(filename); - g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, download_cb, NULL); - g_object_unref(source); - g_object_unref(dest); +static void currency_download_rates() +{ + gchar* filename; + gchar* directory; + GFile* source; + GFile* dest; + + downloading_rates = TRUE; + g_debug("Downloading rates..."); + + filename = get_rate_filepath(); + directory = g_path_get_dirname(filename); + g_mkdir_with_parents(directory, 0755); + g_free(directory); + + /* HACK: It is safe? */ + source = g_file_new_for_uri("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"); + dest = g_file_new_for_path(filename); + g_free(filename); + + g_file_copy_async(source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, download_cb, NULL); + g_object_unref(source); + g_object_unref(dest); } -static void -set_rate (xmlNodePtr node, currency *cur) +static void set_rate(xmlNodePtr node, currency* cur) { - xmlAttrPtr attribute; - for (attribute = node->properties; attribute; attribute = attribute->next) { - if (strcmp((char *)attribute->name, "currency") == 0) { - cur->short_name = (char *)xmlNodeGetContent((xmlNodePtr) attribute); - } else if (strcmp ((char *)attribute->name, "rate") == 0) { - char *val = (char *)xmlNodeGetContent ((xmlNodePtr) attribute); - mp_set_from_string(val, 10, &(cur->value)); - xmlFree (val); - } - } + xmlAttrPtr attribute; + + for (attribute = node->properties; attribute; attribute = attribute->next) + { + if (strcmp((char*) attribute->name, "currency") == 0) + { + cur->short_name = (char*) xmlNodeGetContent((xmlNodePtr) attribute); + } + else if (strcmp ((char*) attribute->name, "rate") == 0) + { + char* val = (char*) xmlNodeGetContent((xmlNodePtr) attribute); + mp_set_from_string(val, 10, &(cur->value)); + xmlFree(val); + } + } } -static void -currency_load_rates() +static void currency_load_rates() { - char *filename = get_rate_filepath(); - xmlDocPtr document; - xmlXPathContextPtr xpath_ctx; - xmlXPathObjectPtr xpath_obj; - int i, len; - - g_return_if_fail(g_file_test(filename, G_FILE_TEST_IS_REGULAR)); - - xmlInitParser(); - document = xmlReadFile(filename, NULL, 0); - g_free (filename); - if (document == NULL) { - fprintf(stderr, "Couldn't parse data file\n"); - return; - } - - xpath_ctx = xmlXPathNewContext(document); - if (xpath_ctx == NULL) { - xmlFreeDoc(document); - fprintf(stderr, "Couldn't create XPath context\n"); - return; - } - - xmlXPathRegisterNs(xpath_ctx, - BAD_CAST("xref"), - BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref")); - xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[@currency][@rate]"), - xpath_ctx); - - if (xpath_obj == NULL) { - xmlXPathFreeContext(xpath_ctx); - xmlFreeDoc(document); - fprintf(stderr, "Couldn't create XPath object\n"); - return; - } - - len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0; - currency_count = len + 1; - currencies = g_slice_alloc0(sizeof(currency) * currency_count); - for (i = 0; i < len; i++) { - if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE) { - set_rate(xpath_obj->nodesetval->nodeTab[i], ¤cies[i]); - } - - // Avoid accessing removed elements - if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL) - xpath_obj->nodesetval->nodeTab[i] = NULL; - } - - currencies[len].short_name = g_strdup("EUR"); - MPNumber foo; - mp_set_from_integer(1, &foo); - currencies[len].value = foo; - - xmlXPathFreeObject(xpath_obj); - xmlXPathFreeContext(xpath_ctx); - xmlFreeDoc(document); - xmlCleanupParser(); - - g_debug("Rates loaded"); - loaded_rates = TRUE; + char* filename = get_rate_filepath(); + xmlDocPtr document; + xmlXPathContextPtr xpath_ctx; + xmlXPathObjectPtr xpath_obj; + int i; + int len; + + g_return_if_fail(g_file_test(filename, G_FILE_TEST_IS_REGULAR)); + + xmlInitParser(); + document = xmlReadFile(filename, NULL, 0); + g_free (filename); + + if (document == NULL) + { + fprintf(stderr, "Couldn't parse data file\n"); + return; + } + + xpath_ctx = xmlXPathNewContext(document); + + if (xpath_ctx == NULL) + { + xmlFreeDoc(document); + fprintf(stderr, "Couldn't create XPath context\n"); + return; + } + + xmlXPathRegisterNs(xpath_ctx, BAD_CAST("xref"), BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref")); + xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[@currency][@rate]"), xpath_ctx); + + if (xpath_obj == NULL) + { + xmlXPathFreeContext(xpath_ctx); + xmlFreeDoc(document); + fprintf(stderr, "Couldn't create XPath object\n"); + return; + } + + len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0; + currency_count = len + 1; + currencies = g_slice_alloc0(sizeof(currency) * currency_count); + + for (i = 0; i < len; i++) + { + if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE) + { + set_rate(xpath_obj->nodesetval->nodeTab[i], ¤cies[i]); + } + + // Avoid accessing removed elements + if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL) + { + xpath_obj->nodesetval->nodeTab[i] = NULL; + } + } + + currencies[len].short_name = g_strdup("EUR"); + MPNumber foo; + mp_set_from_integer(1, &foo); + currencies[len].value = foo; + + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_ctx); + xmlFreeDoc(document); + xmlCleanupParser(); + + g_debug("Rates loaded"); + loaded_rates = TRUE; } -gboolean -currency_convert(const MPNumber *from_amount, - const char *source_currency, const char *target_currency, - MPNumber *to_amount) +gboolean currency_convert(const MPNumber* from_amount, const char* source_currency, const char* target_currency, MPNumber* to_amount) { - int from_index, to_index; - - if (downloading_rates) - return FALSE; - - /* Update currency if necessary */ - if (currency_rates_needs_update()) { - currency_download_rates(); - return FALSE; - } - if (!loaded_rates) - currency_load_rates(); - - from_index = currency_get_index(source_currency); - to_index = currency_get_index(target_currency); - if (from_index < 0 || to_index < 0) - return FALSE; - - if (mp_is_zero(¤cies[from_index].value) || - mp_is_zero(¤cies[to_index].value)) { - mp_set_from_integer(0, to_amount); - return FALSE; - } - - mp_divide(from_amount, ¤cies[from_index].value, to_amount); - mp_multiply(to_amount, ¤cies[to_index].value, to_amount); - - return TRUE; + int from_index, to_index; + + if (downloading_rates) + { + return FALSE; + } + + /* Update currency if necessary */ + if (currency_rates_needs_update()) + { + currency_download_rates(); + return FALSE; + } + + if (!loaded_rates) + { + currency_load_rates(); + } + + from_index = currency_get_index(source_currency); + to_index = currency_get_index(target_currency); + + if (from_index < 0 || to_index < 0) + { + return FALSE; + } + + if (mp_is_zero(¤cies[from_index].value) || mp_is_zero(¤cies[to_index].value)) + { + mp_set_from_integer(0, to_amount); + return FALSE; + } + + mp_divide(from_amount, ¤cies[from_index].value, to_amount); + mp_multiply(to_amount, ¤cies[to_index].value, to_amount); + + return TRUE; } -void -currency_free_resources() +void currency_free_resources() { - int i; - - for (i = 0; i < currency_count; i++) { - if (currencies[i].short_name != NULL) - xmlFree(currencies[i].short_name); - } - g_slice_free1(currency_count * sizeof(currency), currencies); - currencies = NULL; - currency_count = 0; + int i; + + for (i = 0; i < currency_count; i++) + { + if (currencies[i].short_name != NULL) + { + xmlFree(currencies[i].short_name); + } + } + + g_slice_free1(currency_count * sizeof(currency), currencies); + + currencies = NULL; + currency_count = 0; } |