/* util-collection.c generated by valac 0.56.3, the Vala compiler
 * generated from util-collection.vala, do not modify */

/* Copyright 2016 Software Freedom Conservancy Inc.
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

#include "geary-engine.h"
#include <gee.h>
#include <glib-object.h>
#include <glib.h>

#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

/** Returns a modifiable collection containing a single element. */
GeeCollection*
geary_collection_single (GType t_type,
                         GBoxedCopyFunc t_dup_func,
                         GDestroyNotify t_destroy_func,
                         gconstpointer element)
{
	GeeCollection* single = NULL;
	GeeLinkedList* _tmp0_;
	GeeCollection* result;
	_tmp0_ = gee_linked_list_new (t_type, (GBoxedCopyFunc) t_dup_func, (GDestroyNotify) t_destroy_func, NULL, NULL, NULL);
	single = G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEE_TYPE_COLLECTION, GeeCollection);
	gee_collection_add (single, element);
	result = single;
	return result;
}

/** Returns a modifiable map containing a single entry. */
GeeMap*
geary_collection_single_map (GType k_type,
                             GBoxedCopyFunc k_dup_func,
                             GDestroyNotify k_destroy_func,
                             GType v_type,
                             GBoxedCopyFunc v_dup_func,
                             GDestroyNotify v_destroy_func,
                             gconstpointer key,
                             gconstpointer value)
{
	GeeMap* single = NULL;
	GeeHashMap* _tmp0_;
	GeeMap* result;
	_tmp0_ = gee_hash_map_new (k_type, (GBoxedCopyFunc) k_dup_func, (GDestroyNotify) k_destroy_func, v_type, (GBoxedCopyFunc) v_dup_func, (GDestroyNotify) v_destroy_func, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	single = G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEE_TYPE_MAP, GeeMap);
	gee_map_set (single, key, value);
	result = single;
	return result;
}

/** Returns a copy of the given collection in a new collection. */
GeeCollection*
geary_collection_copy (GType v_type,
                       GBoxedCopyFunc v_dup_func,
                       GDestroyNotify v_destroy_func,
                       GeeCollection* original)
{
	GeeLinkedList* copy = NULL;
	GeeLinkedList* _tmp0_;
	GeeCollection* result;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (original, GEE_TYPE_COLLECTION), NULL);
	_tmp0_ = gee_linked_list_new (v_type, (GBoxedCopyFunc) v_dup_func, (GDestroyNotify) v_destroy_func, NULL, NULL, NULL);
	copy = _tmp0_;
	gee_collection_add_all (G_TYPE_CHECK_INSTANCE_CAST (copy, GEE_TYPE_COLLECTION, GeeCollection), original);
	result = G_TYPE_CHECK_INSTANCE_CAST (copy, GEE_TYPE_COLLECTION, GeeCollection);
	return result;
}

/** Returns the first element from a collection. */
gpointer
geary_collection_first (GType g_type,
                        GBoxedCopyFunc g_dup_func,
                        GDestroyNotify g_destroy_func,
                        GeeCollection* c)
{
	GeeIterator* iter = NULL;
	GeeIterator* _tmp0_;
	gpointer _tmp1_ = NULL;
	GeeIterator* _tmp2_;
	gpointer result;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (c, GEE_TYPE_COLLECTION), NULL);
	_tmp0_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (c, GEE_TYPE_ITERABLE, GeeIterable));
	iter = _tmp0_;
	_tmp2_ = iter;
	if (gee_iterator_next (_tmp2_)) {
		GeeIterator* _tmp3_;
		gpointer _tmp4_;
		_tmp3_ = iter;
		_tmp4_ = gee_iterator_get (_tmp3_);
		((_tmp1_ == NULL) || (g_destroy_func == NULL)) ? NULL : (_tmp1_ = (g_destroy_func (_tmp1_), NULL));
		_tmp1_ = _tmp4_;
	} else {
		((_tmp1_ == NULL) || (g_destroy_func == NULL)) ? NULL : (_tmp1_ = (g_destroy_func (_tmp1_), NULL));
		_tmp1_ = NULL;
	}
	result = _tmp1_;
	_g_object_unref0 (iter);
	return result;
}

/**
     * Removes all elements that pass the given predicate.
     *
     * Note that this modifies the supplied Collection.
     */
static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

GeeCollection*
geary_collection_remove_if (GType g_type,
                            GBoxedCopyFunc g_dup_func,
                            GDestroyNotify g_destroy_func,
                            GeeCollection* c,
                            GeePredicate pred,
                            gpointer pred_target,
                            GDestroyNotify pred_target_destroy_notify)
{
	GeeIterator* iter = NULL;
	GeeIterator* _tmp0_;
	GeeCollection* _tmp7_;
	GeeCollection* result;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (c, GEE_TYPE_COLLECTION), NULL);
	_tmp0_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (c, GEE_TYPE_ITERABLE, GeeIterable));
	iter = _tmp0_;
	while (TRUE) {
		GeeIterator* _tmp1_;
		GeeIterator* _tmp2_;
		gpointer _tmp3_;
		gpointer _tmp4_;
		gboolean _tmp5_;
		_tmp1_ = iter;
		if (!gee_iterator_next (_tmp1_)) {
			break;
		}
		_tmp2_ = iter;
		_tmp3_ = gee_iterator_get (_tmp2_);
		_tmp4_ = _tmp3_;
		_tmp5_ = pred (_tmp4_, pred_target);
		((_tmp4_ == NULL) || (g_destroy_func == NULL)) ? NULL : (_tmp4_ = (g_destroy_func (_tmp4_), NULL));
		if (_tmp5_) {
			GeeIterator* _tmp6_;
			_tmp6_ = iter;
			gee_iterator_remove (_tmp6_);
		}
	}
	_tmp7_ = _g_object_ref0 (c);
	result = _tmp7_;
	_g_object_unref0 (iter);
	(pred_target_destroy_notify == NULL) ? NULL : (pred_target_destroy_notify (pred_target), NULL);
	pred = NULL;
	pred_target = NULL;
	pred_target_destroy_notify = NULL;
	return result;
}

/**
     * Sets the dest Map with all keys and values in src.
     */
void
geary_collection_map_set_all (GType k_type,
                              GBoxedCopyFunc k_dup_func,
                              GDestroyNotify k_destroy_func,
                              GType v_type,
                              GBoxedCopyFunc v_dup_func,
                              GDestroyNotify v_destroy_func,
                              GeeMap* dest,
                              GeeMap* src)
{
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (dest, GEE_TYPE_MAP));
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (src, GEE_TYPE_MAP));
	{
		GeeIterator* _key_it = NULL;
		GeeSet* _tmp0_;
		GeeSet* _tmp1_;
		GeeSet* _tmp2_;
		GeeIterator* _tmp3_;
		GeeIterator* _tmp4_;
		_tmp0_ = gee_map_get_keys (src);
		_tmp1_ = _tmp0_;
		_tmp2_ = _tmp1_;
		_tmp3_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (_tmp2_, GEE_TYPE_ITERABLE, GeeIterable));
		_tmp4_ = _tmp3_;
		_g_object_unref0 (_tmp2_);
		_key_it = _tmp4_;
		while (TRUE) {
			GeeIterator* _tmp5_;
			gpointer key = NULL;
			GeeIterator* _tmp6_;
			gpointer _tmp7_;
			gconstpointer _tmp8_;
			gconstpointer _tmp9_;
			gpointer _tmp10_;
			gpointer _tmp11_;
			_tmp5_ = _key_it;
			if (!gee_iterator_next (_tmp5_)) {
				break;
			}
			_tmp6_ = _key_it;
			_tmp7_ = gee_iterator_get (_tmp6_);
			key = _tmp7_;
			_tmp8_ = key;
			_tmp9_ = key;
			_tmp10_ = gee_map_get (src, _tmp9_);
			_tmp11_ = _tmp10_;
			gee_map_set (dest, _tmp8_, _tmp11_);
			((_tmp11_ == NULL) || (v_destroy_func == NULL)) ? NULL : (_tmp11_ = (v_destroy_func (_tmp11_), NULL));
			((key == NULL) || (k_destroy_func == NULL)) ? NULL : (key = (k_destroy_func (key), NULL));
		}
		_g_object_unref0 (_key_it);
	}
}

/**
     * Sets multiple elements with the same key in a MultiMap.
     */
void
geary_collection_multi_map_set_all (GType k_type,
                                    GBoxedCopyFunc k_dup_func,
                                    GDestroyNotify k_destroy_func,
                                    GType v_type,
                                    GBoxedCopyFunc v_dup_func,
                                    GDestroyNotify v_destroy_func,
                                    GeeMultiMap* dest,
                                    gconstpointer key,
                                    GeeCollection* values)
{
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (dest, GEE_TYPE_MULTI_MAP));
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (values, GEE_TYPE_COLLECTION));
	{
		GeeIterator* _value_it = NULL;
		GeeIterator* _tmp0_;
		_tmp0_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (values, GEE_TYPE_ITERABLE, GeeIterable));
		_value_it = _tmp0_;
		while (TRUE) {
			GeeIterator* _tmp1_;
			gpointer value = NULL;
			GeeIterator* _tmp2_;
			gpointer _tmp3_;
			gconstpointer _tmp4_;
			_tmp1_ = _value_it;
			if (!gee_iterator_next (_tmp1_)) {
				break;
			}
			_tmp2_ = _value_it;
			_tmp3_ = gee_iterator_get (_tmp2_);
			value = _tmp3_;
			_tmp4_ = value;
			gee_multi_map_set (dest, key, _tmp4_);
			((value == NULL) || (v_destroy_func == NULL)) ? NULL : (value = (v_destroy_func (value), NULL));
		}
		_g_object_unref0 (_value_it);
	}
}

/**
     * Removes all keys from the Map.
     */
void
geary_collection_map_unset_all_keys (GType k_type,
                                     GBoxedCopyFunc k_dup_func,
                                     GDestroyNotify k_destroy_func,
                                     GType v_type,
                                     GBoxedCopyFunc v_dup_func,
                                     GDestroyNotify v_destroy_func,
                                     GeeMap* map,
                                     GeeCollection* keys)
{
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (map, GEE_TYPE_MAP));
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (keys, GEE_TYPE_COLLECTION));
	{
		GeeIterator* _key_it = NULL;
		GeeIterator* _tmp0_;
		_tmp0_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (keys, GEE_TYPE_ITERABLE, GeeIterable));
		_key_it = _tmp0_;
		while (TRUE) {
			GeeIterator* _tmp1_;
			gpointer key = NULL;
			GeeIterator* _tmp2_;
			gpointer _tmp3_;
			gconstpointer _tmp4_;
			_tmp1_ = _key_it;
			if (!gee_iterator_next (_tmp1_)) {
				break;
			}
			_tmp2_ = _key_it;
			_tmp3_ = gee_iterator_get (_tmp2_);
			key = _tmp3_;
			_tmp4_ = key;
			gee_map_unset (map, _tmp4_, NULL);
			((key == NULL) || (k_destroy_func == NULL)) ? NULL : (key = (k_destroy_func (key), NULL));
		}
		_g_object_unref0 (_key_it);
	}
}

/**
     * Return a MultiMap of value => key of the input map's key => values.
     */
GeeMultiMap*
geary_collection_reverse_multi_map (GType k_type,
                                    GBoxedCopyFunc k_dup_func,
                                    GDestroyNotify k_destroy_func,
                                    GType v_type,
                                    GBoxedCopyFunc v_dup_func,
                                    GDestroyNotify v_destroy_func,
                                    GeeMultiMap* map)
{
	GeeHashMultiMap* reverse = NULL;
	GeeHashMultiMap* _tmp0_;
	GeeMultiMap* result;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (map, GEE_TYPE_MULTI_MAP), NULL);
	_tmp0_ = gee_hash_multi_map_new (v_type, (GBoxedCopyFunc) v_dup_func, (GDestroyNotify) v_destroy_func, k_type, (GBoxedCopyFunc) k_dup_func, (GDestroyNotify) k_destroy_func, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	reverse = _tmp0_;
	{
		GeeIterator* _key_it = NULL;
		GeeSet* _tmp1_;
		GeeSet* _tmp2_;
		GeeIterator* _tmp3_;
		GeeIterator* _tmp4_;
		_tmp1_ = gee_multi_map_get_keys (map);
		_tmp2_ = _tmp1_;
		_tmp3_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (_tmp2_, GEE_TYPE_ITERABLE, GeeIterable));
		_tmp4_ = _tmp3_;
		_g_object_unref0 (_tmp2_);
		_key_it = _tmp4_;
		while (TRUE) {
			GeeIterator* _tmp5_;
			gpointer key = NULL;
			GeeIterator* _tmp6_;
			gpointer _tmp7_;
			_tmp5_ = _key_it;
			if (!gee_iterator_next (_tmp5_)) {
				break;
			}
			_tmp6_ = _key_it;
			_tmp7_ = gee_iterator_get (_tmp6_);
			key = _tmp7_;
			{
				GeeIterator* _value_it = NULL;
				gconstpointer _tmp8_;
				GeeCollection* _tmp9_;
				GeeCollection* _tmp10_;
				GeeIterator* _tmp11_;
				GeeIterator* _tmp12_;
				_tmp8_ = key;
				_tmp9_ = gee_multi_map_get (map, _tmp8_);
				_tmp10_ = _tmp9_;
				_tmp11_ = gee_iterable_iterator (G_TYPE_CHECK_INSTANCE_CAST (_tmp10_, GEE_TYPE_ITERABLE, GeeIterable));
				_tmp12_ = _tmp11_;
				_g_object_unref0 (_tmp10_);
				_value_it = _tmp12_;
				while (TRUE) {
					GeeIterator* _tmp13_;
					gpointer value = NULL;
					GeeIterator* _tmp14_;
					gpointer _tmp15_;
					GeeHashMultiMap* _tmp16_;
					gconstpointer _tmp17_;
					gconstpointer _tmp18_;
					_tmp13_ = _value_it;
					if (!gee_iterator_next (_tmp13_)) {
						break;
					}
					_tmp14_ = _value_it;
					_tmp15_ = gee_iterator_get (_tmp14_);
					value = _tmp15_;
					_tmp16_ = reverse;
					_tmp17_ = value;
					_tmp18_ = key;
					gee_multi_map_set (G_TYPE_CHECK_INSTANCE_CAST (_tmp16_, GEE_TYPE_MULTI_MAP, GeeMultiMap), _tmp17_, _tmp18_);
					((value == NULL) || (v_destroy_func == NULL)) ? NULL : (value = (v_destroy_func (value), NULL));
				}
				_g_object_unref0 (_value_it);
			}
			((key == NULL) || (k_destroy_func == NULL)) ? NULL : (key = (k_destroy_func (key), NULL));
		}
		_g_object_unref0 (_key_it);
	}
	result = G_TYPE_CHECK_INSTANCE_CAST (reverse, GEE_TYPE_MULTI_MAP, GeeMultiMap);
	return result;
}

/**
     * To be used by a Hashable's to_hash() method.
     */
inline guint
geary_collection_int64_hash (gint64 value)
{
	guint result;
	result = geary_collection_hash_memory (&value, (gsize) sizeof (gint64));
	return result;
}

/**
     * To be used as hash_func for Gee collections.
     */
inline guint
geary_collection_int64_hash_func (gint64* n)
{
	guint result;
	result = geary_collection_hash_memory ((guint8*) n, (gsize) sizeof (gint64));
	return result;
}

/**
     * To be used as equal_func for Gee collections.
     */
gboolean
geary_collection_int64_equal_func (gint64* a,
                                   gint64* b)
{
	gint64* bia = NULL;
	gint64* bib = NULL;
	gboolean result;
	bia = (gint64*) a;
	bib = (gint64*) b;
	result = (*bia) == (*bib);
	return result;
}

/**
     * A rotating-XOR hash that can be used to hash memory buffers of any size.
     */
guint
geary_collection_hash_memory (void* ptr,
                              gsize bytes)
{
	gboolean _tmp0_ = FALSE;
	guint8* u8 = NULL;
	guint hash = 0U;
	guint8* _tmp1_;
	guint result;
	if (ptr == NULL) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = bytes == ((gsize) 0);
	}
	if (_tmp0_) {
		result = (guint) 0;
		return result;
	}
	u8 = (guint8*) ptr;
	_tmp1_ = u8;
	hash = (guint) (*_tmp1_);
	{
		gint ctr = 0;
		ctr = 1;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				guint _tmp4_;
				guint _tmp5_;
				guint8* _tmp6_;
				if (!_tmp2_) {
					gint _tmp3_;
					_tmp3_ = ctr;
					ctr = _tmp3_ + 1;
				}
				_tmp2_ = FALSE;
				if (!(((gsize) ctr) < bytes)) {
					break;
				}
				_tmp4_ = hash;
				_tmp5_ = hash;
				_tmp6_ = u8;
				u8 = _tmp6_ + 1;
				hash = ((_tmp4_ << 4) ^ (_tmp5_ >> 28)) ^ (*_tmp6_);
			}
		}
	}
	result = hash;
	return result;
}

/**
     * A rotating-XOR hash that can be used to hash memory buffers of any size until a terminator byte
     * is found.
     *
     * A {@link ByteTransformer} may be supplied to convert bytes before they are hashed.
     *
     * Returns zero if the initial byte is the terminator.
     */
guint
geary_collection_hash_memory_stream (void* ptr,
                                     guint8 terminator,
                                     GearyCollectionByteTransformer cb,
                                     gpointer cb_target)
{
	guint8* u8 = NULL;
	guint hash = 0U;
	guint result;
	u8 = (guint8*) ptr;
	hash = (guint) 0;
	{
		gboolean _tmp0_ = FALSE;
		_tmp0_ = TRUE;
		while (TRUE) {
			guint8 b = 0U;
			guint8* _tmp1_;
			if (!_tmp0_) {
			}
			_tmp0_ = FALSE;
			_tmp1_ = u8;
			u8 = _tmp1_ + 1;
			b = *_tmp1_;
			if (b == terminator) {
				break;
			}
			if (cb != NULL) {
				b = cb (b, cb_target);
			}
			hash = ((hash << 4) ^ (hash >> 28)) ^ b;
		}
	}
	result = hash;
	return result;
}

