Mercurial > pidgin.yaz
comparison libpurple/protocols/myspace/message.c @ 17359:d69bcd74c240
Enhance msim_msg_new() to accept a variadic arguments, like msim_send(),
by means of a new function msim_msg_new_v() accepting a va_list().
This simplifies coding, in that you can now easily create a MsimMessage
with certain fields, and send it later (instead of doing both at once as
with msim_send()).
author | Jeffrey Connelly <jaconnel@calpoly.edu> |
---|---|
date | Mon, 04 Jun 2007 03:30:55 +0000 |
parents | 641c96277fa6 |
children | 3720176bdac6 |
comparison
equal
deleted
inserted
replaced
17358:641c96277fa6 | 17359:d69bcd74c240 |
---|---|
25 static void msim_msg_free_element(gpointer data, gpointer user_data); | 25 static void msim_msg_free_element(gpointer data, gpointer user_data); |
26 static void msim_msg_debug_string_element(gpointer data, gpointer user_data); | 26 static void msim_msg_debug_string_element(gpointer data, gpointer user_data); |
27 static gchar *msim_msg_pack_using(MsimMessage *msg, GFunc gf, gchar *sep, gchar *begin, gchar *end); | 27 static gchar *msim_msg_pack_using(MsimMessage *msg, GFunc gf, gchar *sep, gchar *begin, gchar *end); |
28 static gchar *msim_msg_element_pack(MsimMessageElement *elem); | 28 static gchar *msim_msg_element_pack(MsimMessageElement *elem); |
29 static GList *msim_msg_get_node(MsimMessage *msg, gchar *name); | 29 static GList *msim_msg_get_node(MsimMessage *msg, gchar *name); |
30 | 30 static MsimMessage *msim_msg_new_v(va_list argp); |
31 /** Create a new MsimMessage. */ | 31 |
32 MsimMessage *msim_msg_new(void) | 32 /** Create a new MsimMessage. |
33 { | 33 * |
34 /* Just an empty list. */ | 34 * @param not_empty FALSE if message is empty, TRUE if variadic arguments follow. |
35 return NULL; | 35 * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL. |
36 } | 36 * |
37 | 37 * See msim_msg_append() documentation for details on types. |
38 /** Clone an individual element. | 38 */ |
39 * | 39 MsimMessage *msim_msg_new(gboolean not_empty, ...) |
40 * @param data MsimMessageElement * to clone. | 40 { |
41 * @param user_data Pointer to MsimMessage * to add cloned element to. | 41 va_list argp; |
42 */ | 42 |
43 static void msim_msg_clone_element(gpointer data, gpointer user_data) | 43 va_start(argp, not_empty); |
44 { | 44 |
45 MsimMessageElement *elem; | 45 if (not_empty) |
46 MsimMessage **new; | 46 return msim_msg_new_v(argp); |
47 gpointer new_data; | 47 else |
48 | |
49 elem = (MsimMessageElement *)data; | |
50 new = (MsimMessage **)user_data; | |
51 | |
52 switch (elem->type) | |
53 { | |
54 case MSIM_TYPE_BOOLEAN: | |
55 case MSIM_TYPE_INTEGER: | |
56 new_data = elem->data; | |
57 break; | |
58 | |
59 case MSIM_TYPE_RAW: | |
60 case MSIM_TYPE_STRING: | |
61 new_data = g_strdup((gchar *)elem->data); | |
62 break; | |
63 | |
64 case MSIM_TYPE_BINARY: | |
65 { | |
66 GString *gs; | |
67 | |
68 gs = (GString *)elem->data; | |
69 | |
70 new_data = g_string_new_len(gs->str, gs->len); | |
71 } | |
72 break; | |
73 /* TODO: other types */ | |
74 default: | |
75 purple_debug_info("msim", "msim_msg_clone_element: unknown type %d (%c)\n", elem->type, elem->type); | |
76 g_return_if_fail(NULL); | |
77 } | |
78 | |
79 /* Append cloned data. Note that the 'name' field is a static string, so it | |
80 * never needs to be copied nor freed. */ | |
81 *new = msim_msg_append(*new, elem->name, elem->type, new_data); | |
82 } | |
83 | |
84 /** Clone an existing MsimMessage. | |
85 * | |
86 * @return Cloned message; caller should free with msim_msg_free(). | |
87 */ | |
88 MsimMessage *msim_msg_clone(MsimMessage *old) | |
89 { | |
90 MsimMessage *new; | |
91 | |
92 if (!old) | |
93 return NULL; | 48 return NULL; |
94 | 49 } |
95 new = msim_msg_new(); | 50 |
96 | 51 /** Create a new message from va_list and its first argument. |
97 g_list_foreach(old, msim_msg_clone_element, &new); | 52 * |
98 | 53 * @param argp A va_list of variadic arguments, already started with va_start(). Will be va_end()'d. |
99 return new; | 54 * @return New MsimMessage *, must be freed with msim_msg_free(). |
100 } | 55 * |
101 | 56 * For internal use - users probably want msim_msg_new() or msim_send(). |
102 /** Free an individual message element. | 57 */ |
103 * | 58 static MsimMessage *msim_msg_new_v(va_list argp) |
104 * @param data MsimMessageElement * to free. | 59 { |
105 * @param user_data Not used; required to match g_list_foreach() callback prototype. | |
106 */ | |
107 static void msim_msg_free_element(gpointer data, gpointer user_data) | |
108 { | |
109 MsimMessageElement *elem; | |
110 | |
111 elem = (MsimMessageElement *)data; | |
112 | |
113 switch (elem->type) | |
114 { | |
115 case MSIM_TYPE_BOOLEAN: | |
116 case MSIM_TYPE_INTEGER: | |
117 /* Integer value stored in gpointer - no need to free(). */ | |
118 break; | |
119 | |
120 case MSIM_TYPE_RAW: | |
121 case MSIM_TYPE_STRING: | |
122 /* Always free strings - caller should have g_strdup()'d if | |
123 * string was static or temporary and not to be freed. */ | |
124 g_free(elem->data); | |
125 break; | |
126 | |
127 case MSIM_TYPE_BINARY: | |
128 /* Free the GString itself and the binary data. */ | |
129 g_string_free((GString *)elem->data, TRUE); | |
130 break; | |
131 | |
132 case MSIM_TYPE_DICTIONARY: | |
133 /* TODO: free dictionary */ | |
134 break; | |
135 | |
136 case MSIM_TYPE_LIST: | |
137 /* TODO: free list */ | |
138 break; | |
139 | |
140 default: | |
141 purple_debug_info("msim", "msim_msg_free_element: not freeing unknown type %d (%c)\n", | |
142 elem->type, elem->type); | |
143 break; | |
144 } | |
145 | |
146 g_free(elem); | |
147 } | |
148 | |
149 /** Free a complete message. */ | |
150 void msim_msg_free(MsimMessage *msg) | |
151 { | |
152 if (!msg) | |
153 { | |
154 /* already free as can be */ | |
155 return; | |
156 } | |
157 | |
158 g_list_foreach(msg, msim_msg_free_element, NULL); | |
159 g_list_free(msg); | |
160 } | |
161 | |
162 /** Send an existing MsimMessage. */ | |
163 gboolean msim_msg_send(MsimSession *session, MsimMessage *msg) | |
164 { | |
165 gchar *raw; | |
166 gboolean success; | |
167 | |
168 raw = msim_msg_pack(msg); | |
169 success = msim_send_raw(session, raw); | |
170 g_free(raw); | |
171 | |
172 return success; | |
173 } | |
174 | |
175 /** | |
176 * | |
177 * Send a message to the server, whose contents is specified using | |
178 * variable arguments. | |
179 * | |
180 * @param session | |
181 * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL. | |
182 * | |
183 * This function exists for coding convenience: it allows a message to be created | |
184 * and sent in one line of code. Internally it calls msim_msg_send(). | |
185 * | |
186 * IMPORTANT: See msim_msg_append() documentation for details on element types. | |
187 * | |
188 */ | |
189 gboolean msim_send(MsimSession *session, ...) | |
190 { | |
191 va_list argp; | |
192 gchar *key, *value; | 60 gchar *key, *value; |
193 MsimMessageType type; | 61 MsimMessageType type; |
194 gboolean success; | 62 GString *gs; |
195 MsimMessage *msg; | 63 MsimMessage *msg; |
196 GString *gs; | 64 |
197 | 65 /* Begin with an empty message. */ |
198 msg = msim_msg_new(); | 66 msg = NULL; |
199 | 67 |
200 /* Read key, type, value triplets until NULL. */ | 68 /* Read key, type, value triplets until NULL. */ |
201 va_start(argp, session); | |
202 do | 69 do |
203 { | 70 { |
204 key = va_arg(argp, gchar *); | 71 key = va_arg(argp, gchar *); |
205 if (!key) | 72 if (!key) |
206 { | 73 { |
237 default: | 104 default: |
238 purple_debug_info("msim", "msim_send: unknown type %d (%c)\n", type, type); | 105 purple_debug_info("msim", "msim_send: unknown type %d (%c)\n", type, type); |
239 break; | 106 break; |
240 } | 107 } |
241 } while(key); | 108 } while(key); |
109 va_end(argp); | |
110 | |
111 return msg; | |
112 } | |
113 | |
114 | |
115 /** Clone an individual element. | |
116 * | |
117 * @param data MsimMessageElement * to clone. | |
118 * @param user_data Pointer to MsimMessage * to add cloned element to. | |
119 */ | |
120 static void msim_msg_clone_element(gpointer data, gpointer user_data) | |
121 { | |
122 MsimMessageElement *elem; | |
123 MsimMessage **new; | |
124 gpointer new_data; | |
125 | |
126 elem = (MsimMessageElement *)data; | |
127 new = (MsimMessage **)user_data; | |
128 | |
129 switch (elem->type) | |
130 { | |
131 case MSIM_TYPE_BOOLEAN: | |
132 case MSIM_TYPE_INTEGER: | |
133 new_data = elem->data; | |
134 break; | |
135 | |
136 case MSIM_TYPE_RAW: | |
137 case MSIM_TYPE_STRING: | |
138 new_data = g_strdup((gchar *)elem->data); | |
139 break; | |
140 | |
141 case MSIM_TYPE_BINARY: | |
142 { | |
143 GString *gs; | |
144 | |
145 gs = (GString *)elem->data; | |
146 | |
147 new_data = g_string_new_len(gs->str, gs->len); | |
148 } | |
149 break; | |
150 /* TODO: other types */ | |
151 default: | |
152 purple_debug_info("msim", "msim_msg_clone_element: unknown type %d (%c)\n", elem->type, elem->type); | |
153 g_return_if_fail(NULL); | |
154 } | |
155 | |
156 /* Append cloned data. Note that the 'name' field is a static string, so it | |
157 * never needs to be copied nor freed. */ | |
158 *new = msim_msg_append(*new, elem->name, elem->type, new_data); | |
159 } | |
160 | |
161 /** Clone an existing MsimMessage. | |
162 * | |
163 * @return Cloned message; caller should free with msim_msg_free(). | |
164 */ | |
165 MsimMessage *msim_msg_clone(MsimMessage *old) | |
166 { | |
167 MsimMessage *new; | |
168 | |
169 if (!old) | |
170 return NULL; | |
171 | |
172 new = msim_msg_new(FALSE); | |
173 | |
174 g_list_foreach(old, msim_msg_clone_element, &new); | |
175 | |
176 return new; | |
177 } | |
178 | |
179 /** Free an individual message element. | |
180 * | |
181 * @param data MsimMessageElement * to free. | |
182 * @param user_data Not used; required to match g_list_foreach() callback prototype. | |
183 */ | |
184 static void msim_msg_free_element(gpointer data, gpointer user_data) | |
185 { | |
186 MsimMessageElement *elem; | |
187 | |
188 elem = (MsimMessageElement *)data; | |
189 | |
190 switch (elem->type) | |
191 { | |
192 case MSIM_TYPE_BOOLEAN: | |
193 case MSIM_TYPE_INTEGER: | |
194 /* Integer value stored in gpointer - no need to free(). */ | |
195 break; | |
196 | |
197 case MSIM_TYPE_RAW: | |
198 case MSIM_TYPE_STRING: | |
199 /* Always free strings - caller should have g_strdup()'d if | |
200 * string was static or temporary and not to be freed. */ | |
201 g_free(elem->data); | |
202 break; | |
203 | |
204 case MSIM_TYPE_BINARY: | |
205 /* Free the GString itself and the binary data. */ | |
206 g_string_free((GString *)elem->data, TRUE); | |
207 break; | |
208 | |
209 case MSIM_TYPE_DICTIONARY: | |
210 /* TODO: free dictionary */ | |
211 break; | |
212 | |
213 case MSIM_TYPE_LIST: | |
214 /* TODO: free list */ | |
215 break; | |
216 | |
217 default: | |
218 purple_debug_info("msim", "msim_msg_free_element: not freeing unknown type %d (%c)\n", | |
219 elem->type, elem->type); | |
220 break; | |
221 } | |
222 | |
223 g_free(elem); | |
224 } | |
225 | |
226 /** Free a complete message. */ | |
227 void msim_msg_free(MsimMessage *msg) | |
228 { | |
229 if (!msg) | |
230 { | |
231 /* already free as can be */ | |
232 return; | |
233 } | |
234 | |
235 g_list_foreach(msg, msim_msg_free_element, NULL); | |
236 g_list_free(msg); | |
237 } | |
238 | |
239 /** Send an existing MsimMessage. */ | |
240 gboolean msim_msg_send(MsimSession *session, MsimMessage *msg) | |
241 { | |
242 gchar *raw; | |
243 gboolean success; | |
244 | |
245 raw = msim_msg_pack(msg); | |
246 success = msim_send_raw(session, raw); | |
247 g_free(raw); | |
248 | |
249 return success; | |
250 } | |
251 | |
252 /** | |
253 * | |
254 * Send a message to the server, whose contents is specified using | |
255 * variable arguments. | |
256 * | |
257 * @param session | |
258 * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL. | |
259 * | |
260 * This function exists for coding convenience: it allows a message to be created | |
261 * and sent in one line of code. Internally it calls msim_msg_send(). | |
262 * | |
263 * IMPORTANT: See msim_msg_append() documentation for details on element types. | |
264 * | |
265 */ | |
266 gboolean msim_send(MsimSession *session, ...) | |
267 { | |
268 gboolean success; | |
269 MsimMessage *msg; | |
270 va_list argp; | |
271 | |
272 va_start(argp, session); | |
273 msg = msim_msg_new_v(argp); | |
242 | 274 |
243 /* Actually send the message. */ | 275 /* Actually send the message. */ |
244 success = msim_msg_send(session, msg); | 276 success = msim_msg_send(session, msg); |
245 | 277 |
246 /* Cleanup. */ | 278 /* Cleanup. */ |
247 va_end(argp); | |
248 msim_msg_free(msg); | 279 msim_msg_free(msg); |
249 | 280 |
250 return success; | 281 return success; |
251 } | 282 } |
252 | 283 |
585 | 616 |
586 g_free(raw); | 617 g_free(raw); |
587 return NULL; | 618 return NULL; |
588 } | 619 } |
589 | 620 |
590 msg = msim_msg_new(); | 621 msg = msim_msg_new(FALSE); |
591 | 622 |
592 for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0; | 623 for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0; |
593 (token = tokens[i]); | 624 (token = tokens[i]); |
594 i++) | 625 i++) |
595 { | 626 { |