diff options
Diffstat (limited to 'src/currency.c')
-rw-r--r-- | src/currency.c | 300 |
1 files changed, 60 insertions, 240 deletions
diff --git a/src/currency.c b/src/currency.c index 2add81b..ea81761 100644 --- a/src/currency.c +++ b/src/currency.c @@ -1,276 +1,96 @@ -#include <time.h> +/* + * Copyright (C) 2008-2011 Robert Ancell. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ -#include <glib.h> -#include <glib/gstdio.h> -#include <gio/gio.h> -#include <libxml/tree.h> -#include <libxml/xpath.h> -#include <libxml/xpathInternals.h> +#include <string.h> +#include <stdarg.h> #include "currency.h" -#include "mp.h" - -typedef struct { - char* short_name; - MPNumber value; -} currency; - -static currency* currencies = NULL; -static int currency_count = 0; - -static gboolean downloading_rates = FALSE; -static gboolean loaded_rates = FALSE; - -static char* get_rate_filepath() -{ - return g_build_filename(g_get_user_cache_dir(), "mate-calc", "eurofxref-daily.xml", NULL); -} +#include "mp-serializer.h" +#include "currency-manager.h" // FIXME: Move out of here -static int currency_get_index(const char *short_name) +struct CurrencyPrivate { - int i; + gchar *name; + gchar *display_name; + gchar *symbol; + MPNumber value; +}; - 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; - } - } - } +G_DEFINE_TYPE (Currency, currency, G_TYPE_OBJECT); - 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() +Currency * +currency_new(const gchar *name, + const gchar *display_name, + const gchar *symbol) { - 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); + Currency *currency = g_object_new(currency_get_type(), NULL); - if (difftime(time(NULL), buf.st_mtime) > (60 * 60 * 24 * 7)) - { - return 1; - } + currency->priv->name = g_strdup(name); + currency->priv->display_name = g_strdup(display_name); + currency->priv->symbol = g_strdup(symbol); - return 0; + return currency; } -static void download_cb(GObject* object, GAsyncResult* result, gpointer user_data) +const gchar * +currency_get_name(Currency *currency) { - 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; + g_return_val_if_fail (currency != NULL, NULL); + return currency->priv->name; } -static void currency_download_rates() +const gchar * +currency_get_display_name(Currency *currency) { - 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); + g_return_val_if_fail (currency != NULL, NULL); + return currency->priv->display_name; } -static void set_rate(xmlNodePtr node, currency* cur) +const gchar * +currency_get_symbol(Currency *currency) { - 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); - } - } + g_return_val_if_fail (currency != NULL, NULL); + return currency->priv->symbol; } -static void currency_load_rates() -{ - 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; +void +currency_set_value(Currency *currency, MPNumber *value) +{ + g_return_if_fail (currency != NULL); + g_return_if_fail (value != NULL); + mp_set_from_mp (value, ¤cy->priv->value); } -gboolean currency_convert(const MPNumber* from_amount, const char* source_currency, const char* target_currency, MPNumber* to_amount) +const MPNumber * +currency_get_value(Currency *currency) { - 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; + g_return_val_if_fail (currency != NULL, NULL); + return ¤cy->priv->value; } -void currency_free_resources() -{ - int i; - for (i = 0; i < currency_count; i++) - { - if (currencies[i].short_name != NULL) - { - xmlFree(currencies[i].short_name); - } - } +static void +currency_class_init(CurrencyClass *klass) +{ + g_type_class_add_private(klass, sizeof(CurrencyPrivate)); +} - g_slice_free1(currency_count * sizeof(currency), currencies); - currencies = NULL; - currency_count = 0; +static void +currency_init(Currency *currency) +{ + currency->priv = G_TYPE_INSTANCE_GET_PRIVATE(currency, currency_get_type(), CurrencyPrivate); } |