/* iso_4217.c generated by valac 0.26.2, the Vala compiler
 * generated from iso_4217.vala, do not modify */

/* Copyright © 2012-2013 Tobias Quathamer
 *
 * This file is part of libisocodes.
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/parser.h>
#include <gee.h>


#define LIBISOCODES_TYPE_ISO_CODES (libisocodes_iso_codes_get_type ())
#define LIBISOCODES_ISO_CODES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LIBISOCODES_TYPE_ISO_CODES, libisocodesISO_Codes))
#define LIBISOCODES_ISO_CODES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LIBISOCODES_TYPE_ISO_CODES, libisocodesISO_CodesClass))
#define LIBISOCODES_IS_ISO_CODES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LIBISOCODES_TYPE_ISO_CODES))
#define LIBISOCODES_IS_ISO_CODES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LIBISOCODES_TYPE_ISO_CODES))
#define LIBISOCODES_ISO_CODES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LIBISOCODES_TYPE_ISO_CODES, libisocodesISO_CodesClass))

typedef struct _libisocodesISO_Codes libisocodesISO_Codes;
typedef struct _libisocodesISO_CodesClass libisocodesISO_CodesClass;
typedef struct _libisocodesISO_CodesPrivate libisocodesISO_CodesPrivate;

#define LIBISOCODES_TYPE_ISO_4217 (libisocodes_iso_4217_get_type ())
#define LIBISOCODES_ISO_4217(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LIBISOCODES_TYPE_ISO_4217, libisocodesISO_4217))
#define LIBISOCODES_ISO_4217_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LIBISOCODES_TYPE_ISO_4217, libisocodesISO_4217Class))
#define LIBISOCODES_IS_ISO_4217(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LIBISOCODES_TYPE_ISO_4217))
#define LIBISOCODES_IS_ISO_4217_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LIBISOCODES_TYPE_ISO_4217))
#define LIBISOCODES_ISO_4217_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LIBISOCODES_TYPE_ISO_4217, libisocodesISO_4217Class))

typedef struct _libisocodesISO_4217 libisocodesISO_4217;
typedef struct _libisocodesISO_4217Class libisocodesISO_4217Class;
typedef struct _libisocodesISO_4217Private libisocodesISO_4217Private;

#define LIBISOCODES_TYPE_ISO_4217_ITEM (libisocodes_iso_4217_item_get_type ())
#define LIBISOCODES_ISO_4217_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LIBISOCODES_TYPE_ISO_4217_ITEM, libisocodesISO_4217_Item))
#define LIBISOCODES_ISO_4217_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LIBISOCODES_TYPE_ISO_4217_ITEM, libisocodesISO_4217_ItemClass))
#define LIBISOCODES_IS_ISO_4217_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LIBISOCODES_TYPE_ISO_4217_ITEM))
#define LIBISOCODES_IS_ISO_4217_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LIBISOCODES_TYPE_ISO_4217_ITEM))
#define LIBISOCODES_ISO_4217_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LIBISOCODES_TYPE_ISO_4217_ITEM, libisocodesISO_4217_ItemClass))

typedef struct _libisocodesISO_4217_Item libisocodesISO_4217_Item;
typedef struct _libisocodesISO_4217_ItemClass libisocodesISO_4217_ItemClass;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))

struct _libisocodesISO_Codes {
	GObject parent_instance;
	libisocodesISO_CodesPrivate * priv;
};

struct _libisocodesISO_CodesClass {
	GObjectClass parent_class;
	gchar** (*_get_xpaths) (libisocodesISO_Codes* self, const gchar* code, int* result_length1);
	gchar** (*_get_fields) (libisocodesISO_Codes* self, int* result_length1);
};

struct _libisocodesISO_4217 {
	libisocodesISO_Codes parent_instance;
	libisocodesISO_4217Private * priv;
};

struct _libisocodesISO_4217Class {
	libisocodesISO_CodesClass parent_class;
};

typedef enum  {
	LIBISOCODES_ISO_CODES_ERROR_CANNOT_OPEN_FILE,
	LIBISOCODES_ISO_CODES_ERROR_CANNOT_CREATE_LIBXML_STRUCTURE,
	LIBISOCODES_ISO_CODES_ERROR_CANNOT_PARSE_FILE,
	LIBISOCODES_ISO_CODES_ERROR_FILE_DOES_NOT_CONTAIN_ISO_DATA,
	LIBISOCODES_ISO_CODES_ERROR_CODE_NOT_DEFINED
} libisocodesISOCodesError;
#define LIBISOCODES_ISO_CODES_ERROR libisocodes_iso_codes_error_quark ()

static gpointer libisocodes_iso_4217_parent_class = NULL;

GType libisocodes_iso_codes_get_type (void) G_GNUC_CONST;
GType libisocodes_iso_4217_get_type (void) G_GNUC_CONST;
enum  {
	LIBISOCODES_ISO_4217_DUMMY_PROPERTY
};
libisocodesISO_4217* libisocodes_iso_4217_new (void);
libisocodesISO_4217* libisocodes_iso_4217_construct (GType object_type);
libisocodesISO_Codes* libisocodes_iso_codes_construct (GType object_type);
void libisocodes_iso_4217_setup (libisocodesISO_4217* self);
void _libisocodes_iso_codes_setup_i18n (libisocodesISO_Codes* self);
void libisocodes_iso_codes_set_standard (libisocodesISO_Codes* self, const gchar* value);
void libisocodes_iso_codes_set_filepath (libisocodesISO_Codes* self, const gchar* path);
GType libisocodes_iso_4217_item_get_type (void) G_GNUC_CONST;
GQuark libisocodes_iso_codes_error_quark (void);
libisocodesISO_4217_Item** libisocodes_iso_4217_find_all (libisocodesISO_4217* self, int* result_length1, GError** error);
GeeArrayList* _libisocodes_iso_codes_find_all (libisocodesISO_Codes* self, GError** error);
libisocodesISO_4217_Item* libisocodes_iso_4217_item_new (GeeHashMap* item);
libisocodesISO_4217_Item* libisocodes_iso_4217_item_construct (GType object_type, GeeHashMap* item);
static void _vala_array_add17 (libisocodesISO_4217_Item*** array, int* length, int* size, libisocodesISO_4217_Item* value);
libisocodesISO_4217_Item* libisocodes_iso_4217_find_code (libisocodesISO_4217* self, const gchar* code, GError** error);
GeeHashMap* _libisocodes_iso_codes_find_code (libisocodesISO_Codes* self, const gchar* code, GError** error);
static gchar** libisocodes_iso_4217_real__get_xpaths (libisocodesISO_Codes* base, const gchar* code, int* result_length1);
gboolean _libisocodes_iso_codes_is_number (libisocodesISO_Codes* self, const gchar* text);
static void _vala_array_add18 (gchar*** array, int* length, int* size, gchar* value);
static void _vala_array_add19 (gchar*** array, int* length, int* size, gchar* value);
static gchar** libisocodes_iso_4217_real__get_fields (libisocodesISO_Codes* base, int* result_length1);
static void libisocodes_iso_4217_finalize (GObject* obj);
static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func);


/**
         * Constructor of class.
         * 
         * Call the setup() method, see there for reasoning.
         */
libisocodesISO_4217* libisocodes_iso_4217_construct (GType object_type) {
	libisocodesISO_4217 * self = NULL;
	self = (libisocodesISO_4217*) libisocodes_iso_codes_construct (object_type);
	libisocodes_iso_4217_setup (self);
	return self;
}


libisocodesISO_4217* libisocodes_iso_4217_new (void) {
	return libisocodes_iso_4217_construct (LIBISOCODES_TYPE_ISO_4217);
}


/**
         * Setup of the class.
         * 
         * Due to a bug somewhere in the GObject introspection routines
         * with vala, the constructor of a class is not called when
         * the class is instanciated. Therefore, we use a separate
         * setup method which can be called, if necessary.
         * 
         * For LibXML, it is needed to initialize the parser here.
         */
void libisocodes_iso_4217_setup (libisocodesISO_4217* self) {
	g_return_if_fail (self != NULL);
	_libisocodes_iso_codes_setup_i18n ((libisocodesISO_Codes*) self);
	xmlInitParser ();
	libisocodes_iso_codes_set_standard ((libisocodesISO_Codes*) self, "4217");
	libisocodes_iso_codes_set_filepath ((libisocodesISO_Codes*) self, "/usr/share/xml/iso-codes/iso_4217.xml");
}


/**
         * Return an array of all items in the ISO standard.
         * 
         * @return array All ISO 4217 items.
         */
static gpointer _g_object_ref0 (gpointer self) {
	return self ? g_object_ref (self) : NULL;
}


static void _vala_array_add17 (libisocodesISO_4217_Item*** array, int* length, int* size, libisocodesISO_4217_Item* value) {
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (libisocodesISO_4217_Item*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}


libisocodesISO_4217_Item** libisocodes_iso_4217_find_all (libisocodesISO_4217* self, int* result_length1, GError** error) {
	libisocodesISO_4217_Item** result = NULL;
	libisocodesISO_4217_Item** _result_ = NULL;
	gint _result__length1 = 0;
	gint __result__size_ = 0;
	GeeArrayList* items = NULL;
	GeeArrayList* _tmp0_ = NULL;
	libisocodesISO_4217_Item** _tmp14_ = NULL;
	gint _tmp14__length1 = 0;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_result_ = NULL;
	_result__length1 = 0;
	__result__size_ = _result__length1;
	_tmp0_ = _libisocodes_iso_codes_find_all ((libisocodesISO_Codes*) self, &_inner_error_);
	items = _tmp0_;
	if (G_UNLIKELY (_inner_error_ != NULL)) {
		if (_inner_error_->domain == LIBISOCODES_ISO_CODES_ERROR) {
			g_propagate_error (error, _inner_error_);
			_result_ = (_vala_array_free (_result_, _result__length1, (GDestroyNotify) g_object_unref), NULL);
			return NULL;
		} else {
			_result_ = (_vala_array_free (_result_, _result__length1, (GDestroyNotify) g_object_unref), NULL);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	{
		GeeArrayList* _item_list = NULL;
		GeeArrayList* _tmp1_ = NULL;
		gint _item_size = 0;
		GeeArrayList* _tmp2_ = NULL;
		gint _tmp3_ = 0;
		gint _tmp4_ = 0;
		gint _item_index = 0;
		_tmp1_ = _g_object_ref0 (items);
		_item_list = _tmp1_;
		_tmp2_ = _item_list;
		_tmp3_ = gee_abstract_collection_get_size ((GeeCollection*) _tmp2_);
		_tmp4_ = _tmp3_;
		_item_size = _tmp4_;
		_item_index = -1;
		while (TRUE) {
			gint _tmp5_ = 0;
			gint _tmp6_ = 0;
			gint _tmp7_ = 0;
			GeeHashMap* item = NULL;
			GeeArrayList* _tmp8_ = NULL;
			gint _tmp9_ = 0;
			gpointer _tmp10_ = NULL;
			libisocodesISO_4217_Item** _tmp11_ = NULL;
			gint _tmp11__length1 = 0;
			GeeHashMap* _tmp12_ = NULL;
			libisocodesISO_4217_Item* _tmp13_ = NULL;
			_tmp5_ = _item_index;
			_item_index = _tmp5_ + 1;
			_tmp6_ = _item_index;
			_tmp7_ = _item_size;
			if (!(_tmp6_ < _tmp7_)) {
				break;
			}
			_tmp8_ = _item_list;
			_tmp9_ = _item_index;
			_tmp10_ = gee_abstract_list_get ((GeeAbstractList*) _tmp8_, _tmp9_);
			item = (GeeHashMap*) _tmp10_;
			_tmp11_ = _result_;
			_tmp11__length1 = _result__length1;
			_tmp12_ = item;
			_tmp13_ = libisocodes_iso_4217_item_new (_tmp12_);
			_vala_array_add17 (&_result_, &_result__length1, &__result__size_, _tmp13_);
			_g_object_unref0 (item);
		}
		_g_object_unref0 (_item_list);
	}
	_tmp14_ = _result_;
	_tmp14__length1 = _result__length1;
	if (result_length1) {
		*result_length1 = _tmp14__length1;
	}
	result = _tmp14_;
	_g_object_unref0 (items);
	return result;
}


/**
         * Try to locate the given code in the XML file.
         * 
         * @param string Code to search for.
         * 
         * @return struct A matching ISO 4217 item, if found.
         */
libisocodesISO_4217_Item* libisocodes_iso_4217_find_code (libisocodesISO_4217* self, const gchar* code, GError** error) {
	libisocodesISO_4217_Item* result = NULL;
	GeeHashMap* res = NULL;
	const gchar* _tmp0_ = NULL;
	GeeHashMap* _tmp1_ = NULL;
	libisocodesISO_4217_Item* _tmp2_ = NULL;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (code != NULL, NULL);
	_tmp0_ = code;
	_tmp1_ = _libisocodes_iso_codes_find_code ((libisocodesISO_Codes*) self, _tmp0_, &_inner_error_);
	res = _tmp1_;
	if (G_UNLIKELY (_inner_error_ != NULL)) {
		if (_inner_error_->domain == LIBISOCODES_ISO_CODES_ERROR) {
			g_propagate_error (error, _inner_error_);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	_tmp2_ = libisocodes_iso_4217_item_new (res);
	result = _tmp2_;
	_g_object_unref0 (res);
	return result;
}


/**
         * Set up the XPaths to try.
         * 
         * @param string Code to search for.
         */
static void _vala_array_add18 (gchar*** array, int* length, int* size, gchar* value) {
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (gchar*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}


static void _vala_array_add19 (gchar*** array, int* length, int* size, gchar* value) {
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (gchar*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}


static gchar** libisocodes_iso_4217_real__get_xpaths (libisocodesISO_Codes* base, const gchar* code, int* result_length1) {
	libisocodesISO_4217 * self;
	gchar** result = NULL;
	gchar** xpaths = NULL;
	gchar** _tmp0_ = NULL;
	gint xpaths_length1 = 0;
	gint _xpaths_size_ = 0;
	const gchar* _tmp1_ = NULL;
	gboolean _tmp2_ = FALSE;
	gchar** _tmp17_ = NULL;
	gint _tmp17__length1 = 0;
	self = (libisocodesISO_4217*) base;
	g_return_val_if_fail (code != NULL, NULL);
	_tmp0_ = g_new0 (gchar*, 0 + 1);
	xpaths = _tmp0_;
	xpaths_length1 = 0;
	_xpaths_size_ = xpaths_length1;
	_tmp1_ = code;
	_tmp2_ = _libisocodes_iso_codes_is_number ((libisocodesISO_Codes*) self, _tmp1_);
	if (_tmp2_) {
		gchar** _tmp3_ = NULL;
		gint _tmp3__length1 = 0;
		const gchar* _tmp4_ = NULL;
		gchar* _tmp5_ = NULL;
		gchar* _tmp6_ = NULL;
		gchar* _tmp7_ = NULL;
		gchar* _tmp8_ = NULL;
		gchar* _tmp9_ = NULL;
		_tmp3_ = xpaths;
		_tmp3__length1 = xpaths_length1;
		_tmp4_ = code;
		_tmp5_ = g_utf8_strup (_tmp4_, (gssize) (-1));
		_tmp6_ = _tmp5_;
		_tmp7_ = g_strconcat ("//iso_4217_entry[@numeric_code='", _tmp6_, NULL);
		_tmp8_ = _tmp7_;
		_tmp9_ = g_strconcat (_tmp8_, "']", NULL);
		_vala_array_add18 (&xpaths, &xpaths_length1, &_xpaths_size_, _tmp9_);
		_g_free0 (_tmp8_);
		_g_free0 (_tmp6_);
	} else {
		gchar** _tmp10_ = NULL;
		gint _tmp10__length1 = 0;
		const gchar* _tmp11_ = NULL;
		gchar* _tmp12_ = NULL;
		gchar* _tmp13_ = NULL;
		gchar* _tmp14_ = NULL;
		gchar* _tmp15_ = NULL;
		gchar* _tmp16_ = NULL;
		_tmp10_ = xpaths;
		_tmp10__length1 = xpaths_length1;
		_tmp11_ = code;
		_tmp12_ = g_utf8_strup (_tmp11_, (gssize) (-1));
		_tmp13_ = _tmp12_;
		_tmp14_ = g_strconcat ("//iso_4217_entry[@letter_code='", _tmp13_, NULL);
		_tmp15_ = _tmp14_;
		_tmp16_ = g_strconcat (_tmp15_, "']", NULL);
		_vala_array_add19 (&xpaths, &xpaths_length1, &_xpaths_size_, _tmp16_);
		_g_free0 (_tmp15_);
		_g_free0 (_tmp13_);
	}
	_tmp17_ = xpaths;
	_tmp17__length1 = xpaths_length1;
	if (result_length1) {
		*result_length1 = _tmp17__length1;
	}
	result = _tmp17_;
	return result;
}


/**
         * @inheritDoc
         */
static gchar** libisocodes_iso_4217_real__get_fields (libisocodesISO_Codes* base, int* result_length1) {
	libisocodesISO_4217 * self;
	gchar** result = NULL;
	gchar* _tmp0_ = NULL;
	gchar* _tmp1_ = NULL;
	gchar* _tmp2_ = NULL;
	gchar** _tmp3_ = NULL;
	gchar** _tmp4_ = NULL;
	gint _tmp4__length1 = 0;
	self = (libisocodesISO_4217*) base;
	_tmp0_ = g_strdup ("letter_code");
	_tmp1_ = g_strdup ("numeric_code");
	_tmp2_ = g_strdup ("currency_name");
	_tmp3_ = g_new0 (gchar*, 3 + 1);
	_tmp3_[0] = _tmp0_;
	_tmp3_[1] = _tmp1_;
	_tmp3_[2] = _tmp2_;
	_tmp4_ = _tmp3_;
	_tmp4__length1 = 3;
	if (result_length1) {
		*result_length1 = _tmp4__length1;
	}
	result = _tmp4_;
	return result;
}


static void libisocodes_iso_4217_class_init (libisocodesISO_4217Class * klass) {
	libisocodes_iso_4217_parent_class = g_type_class_peek_parent (klass);
	((libisocodesISO_CodesClass *) klass)->_get_xpaths = libisocodes_iso_4217_real__get_xpaths;
	((libisocodesISO_CodesClass *) klass)->_get_fields = libisocodes_iso_4217_real__get_fields;
	G_OBJECT_CLASS (klass)->finalize = libisocodes_iso_4217_finalize;
}


static void libisocodes_iso_4217_instance_init (libisocodesISO_4217 * self) {
}


static void libisocodes_iso_4217_finalize (GObject* obj) {
	libisocodesISO_4217 * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, LIBISOCODES_TYPE_ISO_4217, libisocodesISO_4217);
	xmlCleanupParser ();
	G_OBJECT_CLASS (libisocodes_iso_4217_parent_class)->finalize (obj);
}


GType libisocodes_iso_4217_get_type (void) {
	static volatile gsize libisocodes_iso_4217_type_id__volatile = 0;
	if (g_once_init_enter (&libisocodes_iso_4217_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (libisocodesISO_4217Class), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) libisocodes_iso_4217_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (libisocodesISO_4217), 0, (GInstanceInitFunc) libisocodes_iso_4217_instance_init, NULL };
		GType libisocodes_iso_4217_type_id;
		libisocodes_iso_4217_type_id = g_type_register_static (LIBISOCODES_TYPE_ISO_CODES, "libisocodesISO_4217", &g_define_type_info, 0);
		g_once_init_leave (&libisocodes_iso_4217_type_id__volatile, libisocodes_iso_4217_type_id);
	}
	return libisocodes_iso_4217_type_id__volatile;
}


static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) {
	if ((array != NULL) && (destroy_func != NULL)) {
		int i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}


static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}



