libpurple/image-store.c

changeset 35804
e97d93132751
parent 35803
caa6f35efd7a
child 35805
1a2cf8aef4a8
--- a/libpurple/image-store.c	Wed Apr 09 20:20:21 2014 +0200
+++ b/libpurple/image-store.c	Thu Apr 10 00:32:00 2014 +0200
@@ -21,36 +21,145 @@
 
 #include "image-store.h"
 
+#include "eventloop.h"
+#include "glibcompat.h"
+
+#define TEMP_IMAGE_TIMEOUT 5
+
+static GHashTable *id_to_image;
+static guint last_id = 0;
+
+/* keys: timeout handle */
+static GHashTable *temp_images = NULL;
+
+/* keys: img id */
+static GSList *perm_images = NULL;
+
+static guint
+image_set_id(PurpleImage *image)
+{
+	/* Use the next unused id number. We do it in a loop on the off chance
+	 * that next id wraps back around to 0 and the hash table still contains
+	 * entries from the first time around.
+	 */
+	while (TRUE) {
+		last_id++;
+
+		if (G_UNLIKELY(last_id == 0))
+			continue;
+
+		if (purple_image_store_get(last_id) == NULL)
+			break;
+	}
+
+	g_object_set_data(G_OBJECT(image), "purple-image-store-id",
+		GINT_TO_POINTER(last_id));
+	g_hash_table_insert(id_to_image, GINT_TO_POINTER(last_id), image);
+	/* TODO: hook map removal after object destruction */
+	return last_id;
+}
+
+static guint
+image_get_id(PurpleImage *image)
+{
+	return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(image),
+		"purple-image-store-id"));
+}
+
 guint
 purple_image_store_add(PurpleImage *image)
 {
-	return 0;
+	guint id;
+
+	g_return_val_if_fail(PURPLE_IS_IMAGE(image), 0);
+
+	id = image_get_id(image);
+	if (id > 0)
+		return id;
+
+	id = image_set_id(image);
+
+	g_object_ref(image);
+	perm_images = g_slist_prepend(perm_images, image);
+
+	return id;
 }
 
 guint
 purple_image_store_add_weak(PurpleImage *image)
 {
-	return 0;
+	guint id;
+
+	g_return_val_if_fail(PURPLE_IS_IMAGE(image), 0);
+
+	id = image_get_id(image);
+	if (id > 0)
+		return id;
+
+	return image_set_id(image);
+}
+
+static gboolean
+remove_temporary(gpointer _image)
+{
+	PurpleImage *image = _image;
+	guint handle;
+
+	handle = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(image),
+		"purple-image-store-handle"));
+
+	g_hash_table_remove(temp_images, GINT_TO_POINTER(handle));
+
+	return G_SOURCE_REMOVE;
 }
 
 guint
 purple_image_store_add_temporary(PurpleImage *image)
 {
-	return 0;
+	guint id;
+	guint handle;
+
+	g_return_val_if_fail(PURPLE_IS_IMAGE(image), 0);
+
+	id = image_get_id(image);
+	if (id > 0)
+		return id;
+
+	id = image_set_id(image);
+
+	g_object_ref(image);
+	handle = purple_timeout_add_seconds(TEMP_IMAGE_TIMEOUT,
+		remove_temporary, image);
+	g_object_set_data(G_OBJECT(image), "purple-image-store-handle",
+		GINT_TO_POINTER(handle));
+	g_hash_table_insert(temp_images, GINT_TO_POINTER(handle), image);
+
+	return id;
 }
 
 PurpleImage *
 purple_image_store_get(guint id)
 {
-	return NULL;
+	return g_hash_table_lookup(id_to_image, GINT_TO_POINTER(id));
 }
 
 void
 _purple_image_store_init(void)
 {
+	id_to_image = g_hash_table_new(g_direct_hash, g_direct_equal);
+	temp_images = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+		NULL, g_object_unref);
 }
 
 void
 _purple_image_store_uninit(void)
 {
+	g_slist_free_full(perm_images, g_object_unref);
+	perm_images = NULL;
+
+	g_hash_table_destroy(temp_images);
+	temp_images = NULL;
+
+	g_hash_table_destroy(id_to_image);
+	id_to_image = NULL;
 }

mercurial