# HG changeset patch # User Jeffrey Connelly # Date 1185077532 0 # Node ID 6d1d86ab6a5920b1c13c09ca64bdf21768117b56 # Parent 8305709dd0b9799aa0cbd8f52a6265fbfb524e37 In MsimMessage, add support for MSIM_TYPE_LIST - pipe-separated lists. diff -r 8305709dd0b9 -r 6d1d86ab6a59 libpurple/protocols/myspace/message.c --- 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. diff -r 8305709dd0b9 -r 6d1d86ab6a59 libpurple/protocols/myspace/message.h --- 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);