diff libpurple/imgstore.c @ 16492:74daf9fc9cf3

merge of '3ee86d1e423ebfd391c26b73ae7ed1b75353d2cf' and '53e71fc52c4d4be3947b2404fe6332ae8d52dc55'
author Ethan Blanton <elb@pidgin.im>
date Fri, 27 Apr 2007 04:03:04 +0000
parents 24bbd7e46bfe
children 2ae39a056179
line wrap: on
line diff
--- a/libpurple/imgstore.c	Fri Apr 27 04:02:51 2007 +0000
+++ b/libpurple/imgstore.c	Fri Apr 27 04:03:04 2007 +0000
@@ -27,140 +27,170 @@
 #include <glib.h>
 #include "debug.h"
 #include "imgstore.h"
+#include "util.h"
 
-static GSList *imgstore = NULL;
+static GHashTable *imgstore;
 static int nextid = 0;
 
 /**
  * Stored image
  *
- * Represents a single IM image awaiting display and/or transmission.
- * Now that this type is basicly private too, these two structs could
- * probably be combined.
+ * NOTE: purple_imgstore_add() creates these without zeroing the memory, so
+ * NOTE: make sure to update that function when adding members.
  */
 struct _PurpleStoredImage
 {
-	char *data;		/**< The image data.		*/
+	int id;
+	guint8 refcount;
 	size_t size;		/**< The image data's size.	*/
 	char *filename;		/**< The filename (for the UI)	*/
+	gpointer data;		/**< The image data.		*/
 };
 
-typedef struct
+PurpleStoredImage *
+purple_imgstore_add(gpointer data, size_t size, const char *filename)
 {
-	int id;
-	int refcount;
 	PurpleStoredImage *img;
-} PurpleStoredImagePriv;
 
-/* private functions */
+	g_return_val_if_fail(data != NULL, 0);
+	g_return_val_if_fail(size > 0, 0);
 
-static PurpleStoredImagePriv *purple_imgstore_get_priv(int id) {
-	GSList *tmp = imgstore;
-	PurpleStoredImagePriv *priv = NULL;
+	img = g_new(PurpleStoredImage, 1);
+	img->data = data;
+	img->size = size;
+	img->filename = g_strdup(filename);
+	img->refcount = 1;
+	img->id = 0;
+
+	return img;
+}
+
+int
+purple_imgstore_add_with_id(gpointer data, size_t size, const char *filename)
+{
+	PurpleStoredImage *img = purple_imgstore_add(data, size, filename);
+	img->id = ++nextid;
 
-	g_return_val_if_fail(id > 0, NULL);
+	g_hash_table_insert(imgstore, GINT_TO_POINTER(img->id), img);
+
+	return img->id;
+}
 
-	while (tmp && !priv) {
-		PurpleStoredImagePriv *tmp_priv = tmp->data;
+PurpleStoredImage *purple_imgstore_find_by_id(int id) {
+	PurpleStoredImage *img = g_hash_table_lookup(imgstore, GINT_TO_POINTER(id));
 
-		if (tmp_priv->id == id)
-			priv = tmp_priv;
+	if (img != NULL)
+		purple_debug_misc("imgstore", "retrieved image id %d\n", img->id);
 
-		tmp = tmp->next;
-	}
+	return img;
+}
+
+gconstpointer purple_imgstore_get_data(PurpleStoredImage *img) {
+	g_return_val_if_fail(img != NULL, NULL);
 
-	if (!priv)
-		purple_debug(PURPLE_DEBUG_ERROR, "imgstore", "failed to find image id %d\n", id);
+	return img->data;
+}
 
-	return priv;
+size_t purple_imgstore_get_size(PurpleStoredImage *img)
+{
+	g_return_val_if_fail(img != NULL, 0);
+
+	return img->size;
 }
 
-static void purple_imgstore_free_priv(PurpleStoredImagePriv *priv) {
-	PurpleStoredImage *img = NULL;
+const char *purple_imgstore_get_filename(PurpleStoredImage *img)
+{
+	g_return_val_if_fail(img != NULL, NULL);
+
+	return img->filename;
+}
+
+const char *purple_imgstore_get_extension(PurpleStoredImage *img)
+{
+	g_return_val_if_fail(img != NULL, NULL);
+
+	return purple_util_get_image_extension(img->data, img->size);
+}
+
+void purple_imgstore_ref_by_id(int id)
+{
+	PurpleStoredImage *img = purple_imgstore_find_by_id(id);
+
+	g_return_if_fail(img != NULL);
+
+	purple_imgstore_ref(img);
+}
+
+void purple_imgstore_unref_by_id(int id)
+{
+	PurpleStoredImage *img = purple_imgstore_find_by_id(id);
+
+	g_return_if_fail(img != NULL);
 
-	g_return_if_fail(priv != NULL);
+	purple_imgstore_unref(img);
+}
+
+PurpleStoredImage *
+purple_imgstore_ref(PurpleStoredImage *img)
+{
+	g_return_val_if_fail(img != NULL, NULL);
+
+	img->refcount++;
+
+	return img;
+}
 
-	img = priv->img;
-	if (img) {
+PurpleStoredImage *
+purple_imgstore_unref(PurpleStoredImage *img)
+{
+	if (img == NULL)
+		return NULL;
+
+	g_return_val_if_fail(img->refcount > 0, NULL);
+
+	img->refcount--;
+
+	if (img->refcount == 0)
+	{
+		purple_signal_emit(purple_imgstore_get_handle(),
+		                   "image-deleting", img);
+		if (img->id)
+			g_hash_table_remove(imgstore, GINT_TO_POINTER(img->id));
+
 		g_free(img->data);
 		g_free(img->filename);
 		g_free(img);
 	}
 
-	purple_debug(PURPLE_DEBUG_INFO, "imgstore", "freed image id %d\n", priv->id);
-
-	g_free(priv);
-
-	imgstore = g_slist_remove(imgstore, priv);
+	return img;
 }
 
-/* public functions */
-
-int purple_imgstore_add(const void *data, size_t size, const char *filename) {
-	PurpleStoredImagePriv *priv;
-	PurpleStoredImage *img;
-
-	g_return_val_if_fail(data != NULL, 0);
-	g_return_val_if_fail(size > 0, 0);
+void *
+purple_imgstore_get_handle()
+{
+	static int handle;
 
-	img = g_new0(PurpleStoredImage, 1);
-	img->data = g_memdup(data, size);
-	img->size = size;
-	img->filename = g_strdup(filename);
-
-	priv = g_new0(PurpleStoredImagePriv, 1);
-	priv->id = ++nextid;
-	priv->refcount = 1;
-	priv->img = img;
-
-	imgstore = g_slist_append(imgstore, priv);
-	purple_debug(PURPLE_DEBUG_INFO, "imgstore", "added image id %d\n", priv->id);
-
-	return priv->id;
+	return &handle;
 }
 
-PurpleStoredImage *purple_imgstore_get(int id) {
-	PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id);
-
-	g_return_val_if_fail(priv != NULL, NULL);
-
-	purple_debug(PURPLE_DEBUG_INFO, "imgstore", "retrieved image id %d\n", priv->id);
-
-	return priv->img;
-}
+void
+purple_imgstore_init()
+{
+	void *handle = purple_imgstore_get_handle();
 
-gpointer purple_imgstore_get_data(PurpleStoredImage *i) {
-	return i->data;
-}
+	purple_signal_register(handle, "image-deleting",
+	                       purple_marshal_VOID__POINTER, NULL,
+	                       1,
+	                       purple_value_new(PURPLE_TYPE_SUBTYPE,
+	                                        PURPLE_SUBTYPE_STORED_IMAGE));
 
-size_t purple_imgstore_get_size(PurpleStoredImage *i) {
-	return i->size;
-}
-
-const char *purple_imgstore_get_filename(PurpleStoredImage *i) {
-	return i->filename;
+	imgstore = g_hash_table_new(g_int_hash, g_int_equal);
 }
 
-void purple_imgstore_ref(int id) {
-	PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id);
-
-	g_return_if_fail(priv != NULL);
-
-	(priv->refcount)++;
-
-	purple_debug(PURPLE_DEBUG_INFO, "imgstore", "referenced image id %d (count now %d)\n", priv->id, priv->refcount);
-}
+void
+purple_imgstore_uninit()
+{
+	g_hash_table_destroy(imgstore);
 
-void purple_imgstore_unref(int id) {
-	PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id);
-
-	g_return_if_fail(priv != NULL);
-	g_return_if_fail(priv->refcount > 0);
-
-	(priv->refcount)--;
-
-	purple_debug(PURPLE_DEBUG_INFO, "imgstore", "unreferenced image id %d (count now %d)\n", priv->id, priv->refcount);
-
-	if (priv->refcount == 0)
-		purple_imgstore_free_priv(priv);
+	purple_signals_unregister_by_instance(purple_blist_get_handle());
 }