changeset 17964:6d1d86ab6a59

In MsimMessage, add support for MSIM_TYPE_LIST - pipe-separated lists.
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Sun, 22 Jul 2007 04:12:12 +0000
parents 8305709dd0b9
children e3687194f2b2
files libpurple/protocols/myspace/message.c libpurple/protocols/myspace/message.h
diffstat 2 files changed, 146 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/myspace/message.c	Sat Jul 21 07:53:22 2007 +0000
+++ b/libpurple/protocols/myspace/message.c	Sun Jul 22 04:12:12 2007 +0000
@@ -62,6 +62,7 @@
 	gchar *key, *value;
 	MsimMessageType type;
 	GString *gs;
+    GList *gl;
 	MsimMessage *msg;
 
 	/* Begin with an empty message. */
@@ -103,6 +104,13 @@
 				msg = msim_msg_append(msg, key, type, gs);
 				break;
 
+            case MSIM_TYPE_LIST:
+                gl = va_arg(argp, GList *);
+
+                g_return_val_if_fail(gl != NULL, FALSE);
+
+                msg = msim_msg_append(msg, key, type, gl);
+
 			default:
 				purple_debug_info("msim", "msim_send: unknown type %d\n", type);
 				break;
@@ -113,6 +121,55 @@
 	return msg;
 }
 
+/** Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free(). */
+GList *
+msim_msg_list_copy(GList *old)
+{
+    GList *new_list;
+
+    new_list = NULL;
+
+    /* Deep copy (g_list_copy is shallow). Copy each string. */
+    for (; old != NULL; old = g_list_next(old))
+    {
+        new_list = g_list_append(new_list, g_strdup(old->data));
+    }
+
+    return new_list;
+}
+
+/** Free a GList * of gchar * strings. */
+void
+msim_msg_list_free(GList *l)
+{
+
+    for (; l != NULL; l = g_list_next(l))
+    {
+        g_free((gchar *)(l->data));
+    }
+    g_list_free(l);
+}
+
+/** Parse a |-separated string into a new GList. Free with msim_msg_list_free(). */
+GList *
+msim_msg_list_parse(const gchar *raw)
+{
+    gchar **array;
+    GList *list;
+    guint i;
+
+    array = g_strsplit(raw, "|", 0);
+    list = NULL;
+    
+    for (i = 0; array[i] != NULL; ++i)
+    {
+        list = g_list_append(list, g_strdup(array[i]));
+    }
+
+    g_strfreev(array);
+
+    return list;
+}
 
 /** Clone an individual element.
  *
@@ -141,6 +198,10 @@
 			new_data = g_strdup((gchar *)elem->data);
 			break;
 
+        case MSIM_TYPE_LIST:
+            new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data));
+            break;
+
 		case MSIM_TYPE_BINARY:
 			{
 				GString *gs;
@@ -216,7 +277,7 @@
 			break;
 			
 		case MSIM_TYPE_LIST:
-			/* TODO: free list */
+            g_list_free((GList *)elem->data);
 			break;
 
 		default:
@@ -237,6 +298,8 @@
 		return;
 	}
 
+    msim_msg_dump("msim_msg_free: freeing %s", msg);
+
 	g_list_foreach(msg, msim_msg_free_element, NULL);
 	g_list_free(msg);
 }
@@ -334,7 +397,7 @@
  *
  * * MSIM_TYPE_DICTIONARY: TODO
  *
- * * MSIM_TYPE_LIST: TODO
+ * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed.
  *
  * */
 MsimMessage *
@@ -449,8 +512,23 @@
 			break;
 			
 		case MSIM_TYPE_LIST:
-			/* TODO: provide human-readable output of list. */
-			string = g_strdup_printf("%s(list): TODO", elem->name);
+            {
+                GString *gs;
+                GList *gl;
+                guint i;
+
+                gs = g_string_new("");
+                g_string_append_printf(gs, "%s(list): \n", elem->name);
+
+                i = 0;
+                for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl))
+                {
+                    g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data));
+                    ++i;
+                }
+                
+                string = gs->str;
+            }
 			break;
 
 		default:
@@ -528,8 +606,20 @@
 			return NULL;
 			
 		case MSIM_TYPE_LIST:
-			/* TODO: pack using a|b|c|d|... */
-			return NULL;
+			/* Pack using a|b|c|d|... */
+            {
+                GString *gs;
+                GList *gl;
+
+                gs = g_string_new("");
+
+                for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl))
+                {
+                    g_string_append_printf(gs, "%s|", (gchar*)(gl->data));
+                }
+                
+                return gs->str;
+            }
 
 		default:
 			purple_debug_info("msim", "field %s, unknown type %d\n", elem->name, elem->type);
@@ -845,6 +935,31 @@
 	}
 }
 
+/** Return an element as a new list. Caller frees with msim_msg_list_free(). */
+GList *
+msim_msg_get_list(MsimMessage *msg, const gchar *name)
+{
+    MsimMessageElement *elem;
+
+    elem = msim_msg_get(msg, name);
+    if (!elem)
+        return NULL;
+
+    switch (elem->type)
+    {
+        case MSIM_TYPE_LIST:
+            return msim_msg_list_copy((GList *)(elem->data));
+
+        case MSIM_TYPE_RAW:
+            return msim_msg_list_parse((gchar *)(elem->data));
+
+        default:
+            purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n",
+                    elem->type, name);
+            return NULL;
+    }
+}
+
 /** Return the data of an element of a given name, as an integer.
  *
  * @param name Name of element.
--- a/libpurple/protocols/myspace/message.h	Sat Jul 21 07:53:22 2007 +0000
+++ b/libpurple/protocols/myspace/message.h	Sun Jul 22 04:12:12 2007 +0000
@@ -54,16 +54,34 @@
 void msim_msg_dump(const char *fmt_string, MsimMessage *msg);
 gchar *msim_msg_pack(MsimMessage *msg);
 
+GList *msim_msg_list_copy(GList *old);
+void msim_msg_list_free(GList *l);
+GList *msim_msg_list_parse(const gchar *raw);
+
 /* Defined in myspace.h */
 struct _MsimSession;
 
-gboolean msim_send(struct _MsimSession *session, ...) 
+/* Based on http://permalink.gmane.org/gmane.comp.parsers.sparse/695 
+ * Define macros for useful gcc attributes. */
 #ifdef __GNUC__
-	/* Cause gcc to emit "a missing sentinel in function call" if forgot
-	 * to write NULL as last, terminating parameter. */
-	__attribute__((__sentinel__(0)))
-#endif
-	;
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1)))
+#define NORETURN_ATTR __attribute__ ((__noreturn__))
+/* __sentinel__ attribute was introduced in gcc 3.5 */
+#if (GCC_VERSION >= 3005)
+  #define SENTINEL_ATTR __attribute__ ((__sentinel__(0)))
+#else
+ #define SENTINEL_ATTR
+#endif /* gcc >= 3.5 */
+#else
+  #define FORMAT_ATTR(pos)
+  #define NORETURN_ATTR
+  #define SENTINEL_ATTR
+#endif 
+
+/* Cause gcc to emit "a missing sentinel in function call" if forgot
+ * to write NULL as last, terminating parameter. */
+gboolean msim_send(struct _MsimSession *session, ...) SENTINEL_ATTR;
 
 gboolean msim_msg_send(struct _MsimSession *session, MsimMessage *msg);
 
@@ -72,6 +90,7 @@
 
 MsimMessageElement *msim_msg_get(MsimMessage *msg, const gchar *name);
 gchar *msim_msg_get_string(MsimMessage *msg, const gchar *name);
+GList *msim_msg_get_list(MsimMessage *msg, const gchar *name);
 guint msim_msg_get_integer(MsimMessage *msg, const gchar *name);
 gboolean msim_msg_get_binary(MsimMessage *msg, const gchar *name, gchar **binary_data, gsize *binary_length);