gmime r1444 - in trunk: . docs/reference gmime



Author: fejj
Date: Sat Sep 13 12:09:01 2008
New Revision: 1444
URL: http://svn.gnome.org/viewvc/gmime?rev=1444&view=rev

Log:
2008-09-13  Jeffrey Stedfast  <fejj novell com>

	Epic optimization hack-a-thon which resulted in another ~5%
	performance improvement.

	* gmime/gmime-message.c (g_mime_message_init): Instead of using a
	hash table for our recipients table, simply use an array since we
	can easily look them up using the GMimeRecipientType as an array
	index. Eliminates unnecessary memory and, most importantly,
	performance overhead.
	(message_add_recipients_from_string): Optimized quite a bit by
	using the new internet_address_list_append/prepend functions.

	* gmime/gmime-utils.c (decode_addrspec): Updated for
	g_mime_decode_domain() changes.

	* gmime/gmime-parse-utils.c (g_mime_decode_domain): Changed the
	API a bit to prevent the need for string duplication/g_free
	overhead in our callers.

	* gmime/gmime-parser.c (parser_fill): Keep track of the stream
	offset ourselves.

	* gmime/internet-address.c (internet_address_list_append): Renamed
	from internet_address_list_concat() and optimized slightly.
	(internet_address_list_prepend): New function that prepends the
	contents of a list to another list.
	(_internet_address_set_name): New internal function which avoids
	emitting a "changed" event in an attempt to enhance the
	performance of internet_address_list_parse().
	(_internet_address_list_add): Same idea as
	_internet_address_set_name(), but also takes ownership of the
	InternetAddress' ref to avoid unnecessary ref/unref overhead.
	(internet_address_mailbox_new): Instead of calling
	internet_address_mailbox_set_addr(), set it manually to avoid a
	g_signal_emit().
	(internet_address_group_new): Call _internet_address_set_name() to
	avoid signal emission.
	(internet_address_group_add_member): Now returns the index of the
	newly added member.
	(decode_mailbox): Avoid string duplication of the addrspec token,
	use the new g_mime_decode_domain() API to avoid unnecessary
	strdup/g_free overhead, and use _internet_address_set_name().
	(decode_address): Don't need to unref members anymore as the lists
	we add them to take ownership of the refs.



Modified:
   trunk/ChangeLog
   trunk/docs/reference/gmime-sections.txt
   trunk/gmime/gmime-message.c
   trunk/gmime/gmime-message.h
   trunk/gmime/gmime-parse-utils.c
   trunk/gmime/gmime-parse-utils.h
   trunk/gmime/gmime-parser.c
   trunk/gmime/gmime-utils.c
   trunk/gmime/internet-address.c
   trunk/gmime/internet-address.h

Modified: trunk/docs/reference/gmime-sections.txt
==============================================================================
--- trunk/docs/reference/gmime-sections.txt	(original)
+++ trunk/docs/reference/gmime-sections.txt	Sat Sep 13 12:09:01 2008
@@ -978,7 +978,6 @@
 internet_address_list_length
 internet_address_list_clear
 internet_address_list_add
-internet_address_list_concat
 internet_address_list_insert
 internet_address_list_remove
 internet_address_list_remove_at
@@ -986,6 +985,8 @@
 internet_address_list_index_of
 internet_address_list_get_address
 internet_address_list_set_address
+internet_address_list_prepend
+internet_address_list_append
 internet_address_list_to_string
 internet_address_list_parse_string
 internet_address_list_writer

Modified: trunk/gmime/gmime-message.c
==============================================================================
--- trunk/gmime/gmime-message.c	(original)
+++ trunk/gmime/gmime-message.c	Sat Sep 13 12:09:01 2008
@@ -144,12 +144,9 @@
 {
 	InternetAddressList *list;
 	GCallback changed_cb;
-	const char *name;
 	
 	changed_cb = recipient_types[type].changed_cb;
-	name = recipient_types[type].name;
-	
-	list = g_hash_table_lookup (message->recipients, name);
+	list = message->recipients[type];
 	
 	return g_signal_handler_find (list, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
 				      0, 0, NULL, changed_cb, message);
@@ -160,7 +157,7 @@
 {
 	InternetAddressList *list;
 	
-	list = g_hash_table_lookup (message->recipients, recipient_types[type].name);
+	list = message->recipients[type];
 	
 	g_signal_connect (list, "changed", recipient_types[type].changed_cb, message);
 }
@@ -171,7 +168,7 @@
 	InternetAddressList *list;
 	gulong id;
 	
-	list = g_hash_table_lookup (message->recipients, recipient_types[type].name);
+	list = message->recipients[type];
 	id = lookup_recipient_changed_id (message, type);
 	g_signal_handler_disconnect (list, id);
 }
@@ -182,7 +179,7 @@
 	InternetAddressList *list;
 	gulong id;
 	
-	list = g_hash_table_lookup (message->recipients, recipient_types[type].name);
+	list = message->recipients[type];
 	id = lookup_recipient_changed_id (message, type);
 	g_signal_handler_block (list, id);
 }
@@ -193,7 +190,7 @@
 	InternetAddressList *list;
 	gulong id;
 	
-	list = g_hash_table_lookup (message->recipients, recipient_types[type].name);
+	list = message->recipients[type];
 	id = lookup_recipient_changed_id (message, type);
 	g_signal_handler_unblock (list, id);
 }
@@ -207,7 +204,7 @@
 	
 	message->from = NULL;
 	message->reply_to = NULL;
-	message->recipients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+	message->recipients = g_new (InternetAddressList *, N_RECIPIENT_TYPES);
 	message->subject = NULL;
 	message->date = 0;
 	message->tz_offset = 0;
@@ -216,8 +213,7 @@
 	
 	/* initialize recipient lists */
 	for (i = 0; i < N_RECIPIENT_TYPES; i++) {
-		list = internet_address_list_new ();
-		g_hash_table_insert (message->recipients, (char *) recipient_types[i].name, list);
+		message->recipients[i] = internet_address_list_new ();
 		connect_changed_event (message, i);
 	}
 	
@@ -249,10 +245,12 @@
 	g_free (message->reply_to);
 	
 	/* disconnect changed handlers */
-	for (i = 0; i < N_RECIPIENT_TYPES; i++)
+	for (i = 0; i < N_RECIPIENT_TYPES; i++) {
 		disconnect_changed_event (message, i);
+		g_object_unref (message->recipients[i]);
+	}
 	
-	g_hash_table_destroy (message->recipients);
+	g_free (message->recipients);
 	
 	g_free (message->subject);
 	
@@ -695,8 +693,6 @@
 message_add_recipients_from_string (GMimeMessage *message, int action, GMimeRecipientType type, const char *str)
 {
 	InternetAddressList *recipients, *addrlist;
-	InternetAddress *ia;
-	int count, i;
 	
 	recipients = g_mime_message_get_recipients (message, type);
 	
@@ -704,14 +700,11 @@
 		internet_address_list_clear (recipients);
 	
 	if ((addrlist = internet_address_list_parse_string (str))) {
-		count = internet_address_list_length (addrlist);
-		for (i = 0; i < count; i++) {
-			ia = internet_address_list_get_address (addrlist, i);
-			if (action == PREPEND)
-				internet_address_list_insert (recipients, i, ia);
-			else
-				internet_address_list_add (recipients, ia);
-		}
+		if (action == PREPEND)
+			internet_address_list_prepend (recipients, addrlist);
+		else
+			internet_address_list_append (recipients, addrlist);
+		
 		g_object_unref (addrlist);
 	}
 }
@@ -875,7 +868,7 @@
 {
 	GMimeMessage *message = (GMimeMessage *) object;
 	InternetAddressList *addrlist;
-	const char *type;
+	GMimeRecipientType type;
 	int i;
 	
 	if (!g_ascii_strcasecmp ("MIME-Version", header))
@@ -905,25 +898,25 @@
 		message->reply_to = NULL;
 		break;
 	case HEADER_TO:
-		type = recipient_types[GMIME_RECIPIENT_TYPE_TO].name;
-		block_changed_event (message, GMIME_RECIPIENT_TYPE_TO);
-		addrlist = g_hash_table_lookup (message->recipients, type);
+		type = GMIME_RECIPIENT_TYPE_TO;
+		block_changed_event (message, type);
+		addrlist = message->recipients[type];
 		internet_address_list_clear (addrlist);
-		unblock_changed_event (message, GMIME_RECIPIENT_TYPE_TO);
+		unblock_changed_event (message, type);
 		break;
 	case HEADER_CC:
-		type = recipient_types[GMIME_RECIPIENT_TYPE_CC].name;
-		block_changed_event (message, GMIME_RECIPIENT_TYPE_CC);
-		addrlist = g_hash_table_lookup (message->recipients, type);
+		type = GMIME_RECIPIENT_TYPE_CC;
+		block_changed_event (message, type);
+		addrlist = message->recipients[type];
 		internet_address_list_clear (addrlist);
-		unblock_changed_event (message, GMIME_RECIPIENT_TYPE_CC);
+		unblock_changed_event (message, type);
 		break;
 	case HEADER_BCC:
-		type = recipient_types[GMIME_RECIPIENT_TYPE_BCC].name;
-		block_changed_event (message, GMIME_RECIPIENT_TYPE_BCC);
-		addrlist = g_hash_table_lookup (message->recipients, type);
+		type = GMIME_RECIPIENT_TYPE_BCC;
+		block_changed_event (message, type);
+		addrlist = message->recipients[type];
 		internet_address_list_clear (addrlist);
-		unblock_changed_event (message, GMIME_RECIPIENT_TYPE_BCC);
+		unblock_changed_event (message, type);
 		break;
 	case HEADER_SUBJECT:
 		g_free (message->subject);
@@ -1179,22 +1172,22 @@
  * @message: MIME Message to change
  * @type: A #GMimeRecipientType
  * @name: The recipient's name (or %NULL)
- * @address: The recipient's address
+ * @addr: The recipient's address
  *
  * Add a recipient of a chosen type to the MIME Message.
  **/
 void
-g_mime_message_add_recipient (GMimeMessage *message, GMimeRecipientType type, const char *name, const char *address)
+g_mime_message_add_recipient (GMimeMessage *message, GMimeRecipientType type, const char *name, const char *addr)
 {
 	InternetAddressList *recipients;
 	InternetAddress *ia;
 	
 	g_return_if_fail (GMIME_IS_MESSAGE (message));
 	g_return_if_fail (type < N_RECIPIENT_TYPES);
-	g_return_if_fail (address != NULL);
+	g_return_if_fail (addr != NULL);
 	
-	recipients = g_hash_table_lookup (message->recipients, recipient_types[type].name);
-	ia = internet_address_mailbox_new (name, address);
+	recipients = message->recipients[type];
+	ia = internet_address_mailbox_new (name, addr);
 	internet_address_list_add (recipients, ia);
 	g_object_unref (ia);
 }
@@ -1213,14 +1206,10 @@
 InternetAddressList *
 g_mime_message_get_recipients (GMimeMessage *message, GMimeRecipientType type)
 {
-	InternetAddressList *list;
-	
 	g_return_val_if_fail (GMIME_IS_MESSAGE (message), NULL);
 	g_return_val_if_fail (type < N_RECIPIENT_TYPES, NULL);
 	
-	list = g_hash_table_lookup (message->recipients, recipient_types[type].name);
-	
-	return list;
+	return message->recipients[type];
 }
 
 
@@ -1241,9 +1230,8 @@
 	
 	g_return_val_if_fail (GMIME_IS_MESSAGE (message), NULL);
 	
-	for (i = 0; i < G_N_ELEMENTS (recipient_types); i++) {
-		if (!(recipients = g_hash_table_lookup (message->recipients, recipient_types[i].name)))
-			continue;
+	for (i = 0; i < N_RECIPIENT_TYPES; i++) {
+		recipients = message->recipients[i];
 		
 		if (internet_address_list_length (recipients) == 0)
 			continue;
@@ -1251,7 +1239,7 @@
 		if (list == NULL)
 			list = internet_address_list_new ();
 		
-		internet_address_list_concat (list, recipients);
+		internet_address_list_append (list, recipients);
 	}
 	
 	return list;

Modified: trunk/gmime/gmime-message.h
==============================================================================
--- trunk/gmime/gmime-message.h	(original)
+++ trunk/gmime/gmime-message.h	Sat Sep 13 12:09:01 2008
@@ -75,8 +75,8 @@
 struct _GMimeMessage {
 	GMimeObject parent_object;
 	
+	InternetAddressList **recipients;
 	GMimeObject *mime_part;
-	GHashTable *recipients;
 	char *message_id;
 	char *reply_to;
 	char *subject;
@@ -102,7 +102,7 @@
 void g_mime_message_set_reply_to (GMimeMessage *message, const char *reply_to);
 const char *g_mime_message_get_reply_to (GMimeMessage *message);
 
-void g_mime_message_add_recipient (GMimeMessage *message, GMimeRecipientType type, const char *name, const char *address);
+void g_mime_message_add_recipient (GMimeMessage *message, GMimeRecipientType type, const char *name, const char *addr);
 InternetAddressList *g_mime_message_get_recipients (GMimeMessage *message, GMimeRecipientType type);
 InternetAddressList *g_mime_message_get_all_recipients (GMimeMessage *message);
 

Modified: trunk/gmime/gmime-parse-utils.c
==============================================================================
--- trunk/gmime/gmime-parse-utils.c	(original)
+++ trunk/gmime/gmime-parse-utils.c	Sat Sep 13 12:09:01 2008
@@ -253,19 +253,18 @@
 /**
  * g_mime_decode_domain:
  * @in: address of input text string
+ * @domain: a #GString to decode the domain into
  *
- * Extracts the next rfc822 'domain' token.
+ * Extracts the next rfc822 'domain' token and appends it to @domain.
  *
- * Returns: the next rfc822 'domain' token or %NULL if non exist.
+ * Returns: %TRUE if an rfc822 'domain' token was decoded or %FALSE
+ * otherwise.
  **/
-char *
-g_mime_decode_domain (const char **in)
+gboolean
+g_mime_decode_domain (const char **in, GString *domain)
 {
 	const char *inptr, *save, *atom;
-	GString *domain;
-	char *dom;
-	
-	domain = g_string_new ("");
+	size_t initial = domain->len;
 	
 	inptr = *in;
 	while (inptr && *inptr) {
@@ -305,14 +304,7 @@
 		inptr++;
 	}
 	
-	if (domain->len)
-		dom = domain->str;
-	else
-		dom = NULL;
-	
-	g_string_free (domain, dom ? FALSE : TRUE);
-	
 	*in = inptr;
 	
-	return dom;
+	return domain->len > initial;
 }

Modified: trunk/gmime/gmime-parse-utils.h
==============================================================================
--- trunk/gmime/gmime-parse-utils.h	(original)
+++ trunk/gmime/gmime-parse-utils.h	Sat Sep 13 12:09:01 2008
@@ -32,8 +32,8 @@
 const char *g_mime_decode_word (const char **in);
 #define decode_word(in) g_mime_decode_word (in)
 
-char *g_mime_decode_domain (const char **in);
-#define decode_domain(in) g_mime_decode_domain (in)
+gboolean g_mime_decode_domain (const char **in, GString *domain);
+#define decode_domain(in, domain) g_mime_decode_domain (in, domain)
 
 G_END_DECLS
 

Modified: trunk/gmime/gmime-parser.c
==============================================================================
--- trunk/gmime/gmime-parser.c	(original)
+++ trunk/gmime/gmime-parser.c	Sat Sep 13 12:09:01 2008
@@ -633,10 +633,10 @@
 	priv->inend = inbuf;
 	inend = priv->realbuf + SCAN_HEAD + SCAN_BUF;
 	
-	if ((nread = g_mime_stream_read (priv->stream, inbuf, inend - inbuf)) > 0)
+	if ((nread = g_mime_stream_read (priv->stream, inbuf, inend - inbuf)) > 0) {
+		priv->offset += nread;
 		priv->inend += nread;
-	
-	priv->offset = g_mime_stream_tell (priv->stream);
+	}
 	
 	return priv->inend - priv->inptr;
 }

Modified: trunk/gmime/gmime-utils.c
==============================================================================
--- trunk/gmime/gmime-utils.c	(original)
+++ trunk/gmime/gmime-utils.c	Sat Sep 13 12:09:01 2008
@@ -827,9 +827,9 @@
 static char *
 decode_addrspec (const char **in)
 {
-	char *domain, *str = NULL;
 	const char *word, *inptr;
 	GString *addrspec;
+	char *str;
 	
 	decode_lwsp (in);
 	inptr = *in;
@@ -861,15 +861,12 @@
 		goto exception;
 	}
 	
-	if (!(domain = decode_domain (&inptr))) {
+	g_string_append_c (addrspec, '@');
+	if (!decode_domain (&inptr, addrspec)) {
 		w(g_warning ("No domain in addr-spec: %s", *in));
 		goto exception;
 	}
 	
-	g_string_append_c (addrspec, '@');
-	g_string_append (addrspec, domain);
-	g_free (domain);
-	
 	str = addrspec->str;
 	g_string_free (addrspec, FALSE);
 	

Modified: trunk/gmime/internet-address.c
==============================================================================
--- trunk/gmime/internet-address.c	(original)
+++ trunk/gmime/internet-address.c	Sat Sep 13 12:09:01 2008
@@ -144,20 +144,11 @@
 }
 
 
-/**
- * internet_address_set_name:
- * @ia: a #InternetAddress
- * @name: the display name for the address group or mailbox
- *
- * Set the display name of the #InternetAddress.
- **/
-void
-internet_address_set_name (InternetAddress *ia, const char *name)
+static void
+_internet_address_set_name (InternetAddress *ia, const char *name)
 {
 	char *buf;
 	
-	g_return_if_fail (IS_INTERNET_ADDRESS (ia));
-	
 	if (name) {
 		buf = g_mime_utils_header_decode_phrase (name);
 		g_mime_utils_unquote_string (buf);
@@ -167,6 +158,21 @@
 		g_free (ia->name);
 		ia->name = NULL;
 	}
+}
+
+/**
+ * internet_address_set_name:
+ * @ia: a #InternetAddress
+ * @name: the display name for the address group or mailbox
+ *
+ * Set the display name of the #InternetAddress.
+ **/
+void
+internet_address_set_name (InternetAddress *ia, const char *name)
+{
+	g_return_if_fail (IS_INTERNET_ADDRESS (ia));
+	
+	_internet_address_set_name (ia, name);
 	
 	g_signal_emit (ia, address_signals[CHANGED], 0);
 }
@@ -189,13 +195,6 @@
 }
 
 
-static void
-_internet_address_to_string (InternetAddress *ia, guint32 flags, size_t *linelen, GString *out)
-{
-	;
-}
-
-
 /**
  * internet_address_to_string:
  * @ia: Internet Address object
@@ -307,11 +306,11 @@
 	
 	g_return_val_if_fail (addr != NULL, NULL);
 	
-	mailbox = g_object_new (INTERNET_ADDRESS_TYPE_MAILBOX, NULL);
-	internet_address_mailbox_set_addr (mailbox, addr);
+	mailbox = g_object_newv (INTERNET_ADDRESS_TYPE_MAILBOX, 0, NULL);
+	mailbox->addr = g_strdup (addr);
 	
 	if (name != NULL)
-		internet_address_set_name ((InternetAddress *) mailbox, name);
+		_internet_address_set_name ((InternetAddress *) mailbox, name);
 	
 	return (InternetAddress *) mailbox;
 }
@@ -447,8 +446,8 @@
 {
 	InternetAddress *group;
 	
-	group = g_object_new (INTERNET_ADDRESS_TYPE_GROUP, NULL);
-	internet_address_set_name (group, name);
+	group = g_object_newv (INTERNET_ADDRESS_TYPE_GROUP, 0, NULL);
+	_internet_address_set_name (group, name);
 	
 	return group;
 }
@@ -507,20 +506,24 @@
 }
 
 
+#define _internet_address_group_add_member(group,member) _internet_address_list_add (group->members, member)
+
 /**
  * internet_address_group_add_member:
  * @group: a #InternetAddressGroup
  * @member: a #InternetAddress
  *
  * Add a contact to the internet address group.
+ *
+ * Returns: the index of the newly added member.
  **/
-void
+int
 internet_address_group_add_member (InternetAddressGroup *group, InternetAddress *member)
 {
 	g_return_if_fail (INTERNET_ADDRESS_IS_GROUP (group));
 	g_return_if_fail (IS_INTERNET_ADDRESS (member));
 	
-	internet_address_list_add (group->members, member);
+	return internet_address_list_add (group->members, member);
 }
 
 
@@ -623,7 +626,7 @@
 InternetAddressList *
 internet_address_list_new (void)
 {
-	return g_object_new (INTERNET_ADDRESS_LIST_TYPE, NULL);
+	return g_object_newv (INTERNET_ADDRESS_LIST_TYPE, 0, NULL);
 }
 
 
@@ -674,6 +677,20 @@
 }
 
 
+static int
+_internet_address_list_add (InternetAddressList *list, InternetAddress *ia)
+{
+	int index;
+	
+	g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
+	
+	index = list->array->len;
+	g_ptr_array_add (list->array, ia);
+	
+	return index;
+}
+
+
 /**
  * internet_address_list_add:
  * @list: a #InternetAddressList
@@ -691,10 +708,7 @@
 	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), -1);
 	g_return_val_if_fail (IS_INTERNET_ADDRESS (ia), -1);
 	
-	g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
-	
-	index = list->array->len;
-	g_ptr_array_add (list->array, ia);
+	index = _internet_address_list_add (list, ia);
 	g_object_ref (ia);
 	
 	g_signal_emit (list, list_signals[CHANGED], 0);
@@ -704,25 +718,67 @@
 
 
 /**
- * internet_address_list_concat:
+ * internet_address_list_prepend:
  * @list: a #InternetAddressList
- * @concat: a #InternetAddressList
+ * @prepend: a #InternetAddressList
  *
- * Adds all of the addresses in @concat to @list.
+ * Inserts all of the addresses in @prepend to the beginning of @list.
  **/
 void
-internet_address_list_concat (InternetAddressList *list, InternetAddressList *concat)
+internet_address_list_prepend (InternetAddressList *list, InternetAddressList *prepend)
 {
 	InternetAddress *ia;
-	guint i;
+	char *dest, *src;
+	guint len, i;
 	
-	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (concat));
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (prepend));
 	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (list));
 	
-	for (i = 0; i < concat->array->len; i++) {
-		ia = (InternetAddress *) concat->array->pdata[i];
+	if (prepend->array->len == 0)
+		return;
+	
+	len = prepend->array->len;
+	g_ptr_array_set_size (list->array, list->array->len + len);
+	
+	src = ((char *) list->array->pdata);
+	dest = src + (sizeof (void *) * len);
+	
+	g_memmove (dest, src, (sizeof (void *) * list->array->len));
+	
+	for (i = 0; i < prepend->array->len; i++) {
+		ia = (InternetAddress *) prepend->array->pdata[i];
 		g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
-		g_ptr_array_add (list->array, ia);
+		list->array->pdata[i] = ia;
+		g_object_ref (ia);
+	}
+	
+	g_signal_emit (list, list_signals[CHANGED], 0);
+}
+
+
+/**
+ * internet_address_list_append:
+ * @list: a #InternetAddressList
+ * @append: a #InternetAddressList
+ *
+ * Adds all of the addresses in @append to @list.
+ **/
+void
+internet_address_list_append (InternetAddressList *list, InternetAddressList *append)
+{
+	InternetAddress *ia;
+	guint len, i;
+	
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (append));
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (list));
+	
+	len = list->array->len;
+	g_ptr_array_set_size (list->array, len + append->array->len);
+	
+	for (i = 0; i < append->array->len; i++) {
+		ia = (InternetAddress *) append->array->pdata[i];
+		g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
+		list->array->pdata[len + i] = ia;
 		g_object_ref (ia);
 	}
 	
@@ -1279,14 +1335,13 @@
 	
 	/* we should be at the '@' now... */
 	if (*inptr == '@') {
-		char *domain;
+		size_t len = addr->len;
 		
+		g_string_append_c (addr, '@');
 		inptr++;
-		if ((domain = decode_domain (&inptr))) {
-			g_string_append_c (addr, '@');
-			g_string_append (addr, domain);
-			g_free (domain);
-		}
+		
+		if (!decode_domain (&inptr, addr))
+			g_string_truncate (addr, len);
 	} else {
 		w(g_warning ("No domain in email address: %s", *in));
 	}
@@ -1343,10 +1398,14 @@
 			g_free (utf8);
 		}
 		
-		mailbox = internet_address_mailbox_new (name ? name->str : NULL, addr->str);
+		mailbox = g_object_newv (INTERNET_ADDRESS_TYPE_MAILBOX, 0, NULL);
+		((InternetAddressMailbox *) mailbox)->addr = addr->str;
+		
+		if (name)
+			_internet_address_set_name (mailbox, name->str);
 	}
 	
-	g_string_free (addr, TRUE);
+	g_string_free (addr, mailbox ? FALSE : TRUE);
 	if (name)
 		g_string_free (name, TRUE);
 	
@@ -1385,19 +1444,15 @@
 		while (*inptr && *inptr != ';') {
 			InternetAddress *member;
 			
-			if ((member = decode_mailbox (&inptr))) {
-				internet_address_group_add_member (group, member);
-				g_object_unref (member);
-			}
+			if ((member = decode_mailbox (&inptr)))
+				_internet_address_group_add_member (group, member);
 			
 			decode_lwsp (&inptr);
 			while (*inptr == ',') {
 				inptr++;
 				decode_lwsp (&inptr);
-				if ((member = decode_mailbox (&inptr))) {
-					internet_address_group_add_member (group, member);
-					g_object_unref (member);
-				}
+				if ((member = decode_mailbox (&inptr)))
+					_internet_address_group_add_member (group, member);
 				
 				decode_lwsp (&inptr);
 			}
@@ -1445,8 +1500,7 @@
 		start = inptr;
 		
 		if ((addr = decode_address (&inptr))) {
-			internet_address_list_add (addrlist, addr);
-			g_object_unref (addr);
+			_internet_address_list_add (addrlist, addr);
 		} else {
 			w(g_warning ("Invalid or incomplete address: %.*s",
 				     inptr - start, start));

Modified: trunk/gmime/internet-address.h
==============================================================================
--- trunk/gmime/internet-address.h	(original)
+++ trunk/gmime/internet-address.h	Sat Sep 13 12:09:01 2008
@@ -148,7 +148,7 @@
 void internet_address_group_set_members (InternetAddressGroup *group, InternetAddressList *members);
 InternetAddressList *internet_address_group_get_members (InternetAddressGroup *group);
 
-void internet_address_group_add_member (InternetAddressGroup *group, InternetAddress *member);
+int internet_address_group_add_member (InternetAddressGroup *group, InternetAddress *member);
 
 
 /**
@@ -179,7 +179,8 @@
 void internet_address_list_clear (InternetAddressList *list);
 
 int internet_address_list_add (InternetAddressList *list, InternetAddress *ia);
-void internet_address_list_concat (InternetAddressList *list, InternetAddressList *concat);
+void internet_address_list_prepend (InternetAddressList *list, InternetAddressList *prepend);
+void internet_address_list_append (InternetAddressList *list, InternetAddressList *append);
 void internet_address_list_insert (InternetAddressList *list, int index, InternetAddress *ia);
 gboolean internet_address_list_remove (InternetAddressList *list, InternetAddress *ia);
 gboolean internet_address_list_remove_at (InternetAddressList *list, int index);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]