gmime r1330 - in trunk: . gmime mono tests



Author: fejj
Date: Tue Jun  3 02:42:03 2008
New Revision: 1330
URL: http://svn.gnome.org/viewvc/gmime?rev=1330&view=rev

Log:
2008-06-02  Jeffrey Stedfast  <fejj novell com>

	* gmime/gmime-message-partial.c (message_partial_message_new): Use
	an iter on the stack.

	* gmime/gmime-header.[c,h]: Changed iters again. Iters are now
	able to be allocated on the stack by making the struct public,
	however this means that they are more sensitive to changes in the
	HeaderList (e.g. all iters other than the one used to remove a
	header become invalid regardless of whether or not the header they
	refer to still exists).



Modified:
   trunk/ChangeLog
   trunk/gmime/gmime-header.c
   trunk/gmime/gmime-header.h
   trunk/gmime/gmime-message-partial.c
   trunk/mono/GMime.metadata
   trunk/mono/gmime-api.raw
   trunk/tests/test-headers.c

Modified: trunk/gmime/gmime-header.c
==============================================================================
--- trunk/gmime/gmime-header.c	(original)
+++ trunk/gmime/gmime-header.c	Tue Jun  3 02:42:03 2008
@@ -56,8 +56,6 @@
  * A message/rfc822 header.
  **/
 
-typedef struct _GMimeHeader GMimeHeader;
-
 struct _GMimeHeader {
 	GMimeHeader *next;
 	GMimeHeader *prev;
@@ -66,23 +64,15 @@
 	char *value;
 };
 
-struct _GMimeHeaderIter {
-	GMimeHeaderIter *next;
-	GMimeHeaderIter *prev;
-	GMimeHeaderList *hdrlist;
-	GMimeHeader *cursor;
-};
-
 struct _GMimeHeaderList {
 	GHashTable *writers;
 	GHashTable *hash;
-	List iters;
+	guint32 version;
 	List list;
 	char *raw;
 };
 
 
-static void g_mime_header_list_invalidate_iters (GMimeHeaderList *headers, GMimeHeader *header);
 static GMimeHeader *g_mime_header_new (const char *name, const char *value, gint64 offset);
 static void g_mime_header_free (GMimeHeader *header);
 
@@ -131,9 +121,12 @@
 /**
  * g_mime_header_iter_new:
  *
- * Instantiate a new #GMimeHeaderIter.
+ * Dynamically allocates a #GMimeHeaderIter on the heap. This is
+ * intended for use in language bindings but may also be useful in
+ * applications as well. You must free this iter with
+ * g_mime_header_iter_free().
  *
- * Returns: a new #GMimeHeaderIter.
+ * Returns: a newly-allocated #GMimeHeaderIter.
  **/
 GMimeHeaderIter *
 g_mime_header_iter_new (void)
@@ -143,8 +136,7 @@
 	iter = g_new (GMimeHeaderIter, 1);
 	iter->hdrlist = NULL;
 	iter->cursor = NULL;
-	iter->next = NULL;
-	iter->prev = NULL;
+	iter->version = 0;
 	
 	return iter;
 }
@@ -154,9 +146,10 @@
  * g_mime_header_iter_copy:
  * @iter: a #GMimeHeaderIter
  *
- * Copies a header iterator.
+ * Creates a dynamically allocated header iterator as a copy of
+ * @iter. You must free this iter with g_mime_header_iter_free().
  *
- * Returns: a new #GMimeHeaderIter which matches @iter's state.
+ * Returns: a newly-allocated copy of @iter.
  **/
 GMimeHeaderIter *
 g_mime_header_iter_copy (GMimeHeaderIter *iter)
@@ -166,14 +159,7 @@
 	g_return_val_if_fail (iter != NULL, NULL);
 	
 	copy = g_mime_header_iter_new ();
-	if (!g_mime_header_iter_is_valid (iter))
-		return copy;
-	
-	copy->hdrlist = iter->hdrlist;
-	copy->cursor = iter->cursor;
-	
-	if (iter->hdrlist)
-		list_append (&iter->hdrlist->iters, (ListNode *) copy);
+	memcpy (copy, iter, sizeof (GMimeHeaderIter));
 	
 	return copy;
 }
@@ -185,27 +171,14 @@
  * @dest: a #GMimeHeaderIter
  *
  * Copies @src to @dest.
- *
- * Returns: %TRUE if the copy was successful or %FALSE otherwise.
  **/
-gboolean
+void
 g_mime_header_iter_copy_to (GMimeHeaderIter *src, GMimeHeaderIter *dest)
 {
 	g_return_if_fail (dest != NULL);
 	g_return_if_fail (src != NULL);
 	
-	if (!g_mime_header_iter_is_valid (src))
-		return FALSE;
-	
-	/* might already reference another hdrlist... */
-	if (dest->hdrlist && dest->next)
-		list_unlink ((ListNode *) dest);
-	
-	list_append (&src->hdrlist->iters, (ListNode *) dest);
-	dest->hdrlist = src->hdrlist;
-	dest->cursor = src->cursor;
-	
-	return TRUE;
+	memcpy (dest, src, sizeof (GMimeHeaderIter));
 }
 
 
@@ -213,16 +186,14 @@
  * g_mime_header_iter_free:
  * @iter: a #GMimeHeaderIter
  *
- * Frees a #GMimeHeaderIter.
+ * Frees a dynamically-allocated #GMimeHeaderIter as created by
+ * g_mime_header_iter_new() or g_mime_header_iter_copy().
  **/
 void
 g_mime_header_iter_free (GMimeHeaderIter *iter)
 {
 	g_return_if_fail (iter != NULL);
 	
-	if (iter->hdrlist && iter->next)
-		list_unlink ((ListNode *) iter);
-	
 	g_free (iter);
 }
 
@@ -243,7 +214,9 @@
 	g_return_val_if_fail (iter1 != NULL, FALSE);
 	g_return_val_if_fail (iter2 != NULL, FALSE);
 	
-	return iter1->cursor == iter2->cursor;
+	return iter1->hdrlist == iter2->hdrlist &&
+		iter1->version == iter2->version &&
+		iter1->cursor == iter2->cursor;
 }
 
 
@@ -252,8 +225,8 @@
  * @iter: a #GMimeHeaderIter
  *
  * Checks if a #GMimeHeaderIter is valid. An iterator may become
- * invalid if the #GMimeHeaderList that the iterator refers to changes
- * or is destroyed.
+ * invalid if the #GMimeHeaderList that the iterator refers to
+ * changes.
  *
  * Returns: %TRUE if @iter is still valid or %FALSE otherwise.
  **/
@@ -262,7 +235,10 @@
 {
 	g_return_val_if_fail (iter != NULL, FALSE);
 	
-	return iter->cursor && iter->cursor->next;
+	if (!iter->hdrlist || !iter->cursor || !iter->cursor->next)
+		return FALSE;
+	
+	return iter->version == iter->hdrlist->version;
 }
 
 
@@ -289,6 +265,7 @@
 	if (!first->next)
 		return FALSE;
 	
+	iter->version = iter->hdrlist->version;
 	iter->cursor = first;
 	
 	return TRUE;
@@ -318,6 +295,7 @@
 	if (!last->next)
 		return FALSE;
 	
+	iter->version = iter->hdrlist->version;
 	iter->cursor = last;
 	
 	return TRUE;
@@ -477,7 +455,10 @@
  *
  * Removes the current header and advances to the next header.
  *
- * Returns: %TRUE on success or %FALSE otherwise
+ * Note: If you remove the last header in the list, then @iter will
+ * become invalid regardless of whether or not other headers remain.
+ *
+ * Returns: %TRUE on success or %FALSE otherwise.
  **/
 gboolean
 g_mime_header_iter_remove (GMimeHeaderIter *iter)
@@ -516,12 +497,12 @@
 	}
 	
 	/* remove/free the header */
-	g_mime_header_list_invalidate_iters (iter->hdrlist, cursor);
 	list_unlink ((ListNode *) cursor);
 	g_mime_header_free (cursor);
+	hdrlist->version++;
 	
-	/* restore iter state */
-	iter->hdrlist = hdrlist;
+	/* update iter state */
+	iter->version = hdrlist->version;
 	iter->cursor = next;
 	
 	return TRUE;
@@ -529,38 +510,6 @@
 
 
 /**
- * g_mime_header_list_invalidate_iters:
- * @headers: a #GMimeHeaderList
- * @header: a #GMimeHeader
- *
- * Invalidate all outstanding iterators that are currently referencing
- * @header. If @header is %NULL, then invalidate all iterators.
- **/
-static void
-g_mime_header_list_invalidate_iters (GMimeHeaderList *headers, GMimeHeader *header)
-{
-	GMimeHeaderIter *iter, *next;
-	
-	/* invalidate all our outstanding iterators matching @header */
-	iter = (GMimeHeaderIter *) headers->iters.head;
-	while (iter->next) {
-		next = iter->next;
-		
-		if (!header || iter->cursor == header) {
-			/* invalidate this iter */
-			list_unlink ((ListNode *) iter);
-			iter->hdrlist = NULL;
-			iter->cursor = NULL;
-			iter->next = NULL;
-			iter->prev = NULL;
-		}
-		
-		iter = next;
-	}
-}
-
-
-/**
  * g_mime_header_list_new:
  *
  * Creates a new #GMimeHeaderList object.
@@ -578,8 +527,8 @@
 						  g_free, NULL);
 	headers->hash = g_hash_table_new (g_mime_strcase_hash,
 					  g_mime_strcase_equal);
-	list_init (&headers->iters);
 	list_init (&headers->list);
+	headers->version = 0;
 	headers->raw = NULL;
 	
 	return headers;
@@ -596,14 +545,10 @@
 g_mime_header_list_destroy (GMimeHeaderList *headers)
 {
 	GMimeHeader *header, *next;
-	GMimeHeaderIter *iter;
 	
 	if (!headers)
 		return;
 	
-	/* invalidate all our outstanding iterators */
-	g_mime_header_list_invalidate_iters (headers, NULL);
-	
 	header = (GMimeHeader *) headers->list.head;
 	while (header->next) {
 		next = header->next;
@@ -766,7 +711,7 @@
 	}
 	
 	/* invalidate all our outstanding iterators matching @header */
-	g_mime_header_list_invalidate_iters (headers, header);
+	headers->version++;
 	
 	/* remove/free the header */
 	list_unlink ((ListNode *) header);
@@ -798,11 +743,7 @@
 	if (!cursor->next)
 		return FALSE;
 	
-	/* might already reference another header list */
-	if (iter->hdrlist && iter->next)
-		list_unlink ((ListNode *) iter);
-	
-	list_append (&headers->iters, (ListNode *) iter);
+	iter->version = headers->version;
 	iter->hdrlist = headers;
 	iter->cursor = cursor;
 	

Modified: trunk/gmime/gmime-header.h
==============================================================================
--- trunk/gmime/gmime-header.h	(original)
+++ trunk/gmime/gmime-header.h	Tue Jun  3 02:42:03 2008
@@ -27,6 +27,9 @@
 
 G_BEGIN_DECLS
 
+typedef struct _GMimeHeader GMimeHeader;
+
+
 /**
  * GMimeHeaderList:
  *
@@ -37,16 +40,27 @@
 
 /**
  * GMimeHeaderIter:
+ * @hdrlist: a #GMimeHeaderList
+ * @cursor: a #GMimeHeader
+ * @version: the version of @hdrlist when initialized
  *
- * A message or mime-part header iterator.
+ * A message or mime-part header iterator. All members should be
+ * considered private.
  **/
 typedef struct _GMimeHeaderIter GMimeHeaderIter;
 
+struct _GMimeHeaderIter {
+	GMimeHeaderList *hdrlist;
+	GMimeHeader *cursor;
+	guint32 version;
+};
+
+
 GMimeHeaderIter *g_mime_header_iter_new (void);
 void g_mime_header_iter_free (GMimeHeaderIter *iter);
 
 GMimeHeaderIter *g_mime_header_iter_copy (GMimeHeaderIter *iter);
-gboolean g_mime_header_iter_copy_to (GMimeHeaderIter *src, GMimeHeaderIter *dest);
+void g_mime_header_iter_copy_to (GMimeHeaderIter *src, GMimeHeaderIter *dest);
 
 gboolean g_mime_header_iter_equal (GMimeHeaderIter *iter1, GMimeHeaderIter *iter2);
 

Modified: trunk/gmime/gmime-message-partial.c
==============================================================================
--- trunk/gmime/gmime-message-partial.c	(original)
+++ trunk/gmime/gmime-message-partial.c	Tue Jun  3 02:42:03 2008
@@ -390,23 +390,20 @@
 	const char *name, *value;
 	GMimeMessage *message;
 	GMimeHeaderList *list;
-	GMimeHeaderIter *iter;
+	GMimeHeaderIter iter;
 	
 	message = g_mime_message_new (FALSE);
 	
 	list = ((GMimeObject *) base)->headers;
-	iter = g_mime_header_iter_new ();
 	
-	if (g_mime_header_list_get_iter (list, iter)) {
+	if (g_mime_header_list_get_iter (list, &iter)) {
 		do {
-			name = g_mime_header_iter_get_name (iter);
-			value = g_mime_header_iter_get_value (iter);
+			name = g_mime_header_iter_get_name (&iter);
+			value = g_mime_header_iter_get_value (&iter);
 			g_mime_object_append_header ((GMimeObject *) message, name, value);
-		} while (g_mime_header_iter_next (iter));
+		} while (g_mime_header_iter_next (&iter));
 	}
 	
-	g_mime_header_iter_free (iter);
-	
 	return message;
 }
 

Modified: trunk/mono/GMime.metadata
==============================================================================
--- trunk/mono/GMime.metadata	(original)
+++ trunk/mono/GMime.metadata	Tue Jun  3 02:42:03 2008
@@ -117,6 +117,11 @@
   <!-- Header -->
   <attr path="/api/namespace/struct[ cname='GMimeHeaderList']/method[ name='HasRaw']" name="hidden">true</attr>
   <attr path="/api/namespace/struct[ cname='GMimeHeaderList']/method[ name='SetRaw']" name="hidden">true</attr>
+  <attr path="/api/namespace/struct[ cname='GMimeHeaderIter']/method[ name='SetValue']/return-type" name="type">void</attr>
+  <attr path="/api/namespace/struct[ cname='GMimeHeaderIter']" name="opaque">true</attr>
+  <remove-node path="/api/namespace/struct[ cname='GMimeHeaderIter']/field[ cname='hdrlist']"/>
+  <remove-node path="/api/namespace/struct[ cname='GMimeHeaderIter']/field[ cname='version']"/>
+  <remove-node path="/api/namespace/struct[ cname='GMimeHeaderIter']/field[ cname='cursor']"/>
 
   <!-- iconv -->
   

Modified: trunk/mono/gmime-api.raw
==============================================================================
--- trunk/mono/gmime-api.raw	(original)
+++ trunk/mono/gmime-api.raw	Tue Jun  3 02:42:03 2008
@@ -2107,10 +2107,20 @@
         </parameters>
       </method>
     </struct>
+    <struct name="Header" cname="GMimeHeader" opaque="true" />
     <struct name="HeaderIter" cname="GMimeHeaderIter" opaque="true">
+      <field name="Hdrlist" cname="hdrlist" type="GMimeHeaderList*" access="public" writeable="true" />
+      <field name="Cursor" cname="cursor" type="GMimeHeader*" access="public" writeable="true" />
+      <field name="Version" cname="version" type="guint32" access="public" writeable="true" />
       <method name="Copy" cname="g_mime_header_iter_copy">
         <return-type type="GMimeHeaderIter*" owned="true" />
       </method>
+      <method name="CopyTo" cname="g_mime_header_iter_copy_to">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GMimeHeaderIter*" name="dest" />
+        </parameters>
+      </method>
       <method name="Equal" cname="g_mime_header_iter_equal">
         <return-type type="gboolean" />
         <parameters>
@@ -2138,6 +2148,7 @@
       <method name="Last" cname="g_mime_header_iter_last">
         <return-type type="gboolean" />
       </method>
+      <constructor cname="g_mime_header_iter_new" />
       <method name="Next" cname="g_mime_header_iter_next">
         <return-type type="gboolean" />
       </method>
@@ -2172,7 +2183,10 @@
         </parameters>
       </method>
       <method name="GetIter" cname="g_mime_header_list_get_iter">
-        <return-type type="GMimeHeaderIter*" />
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="GMimeHeaderIter*" name="iter" />
+        </parameters>
       </method>
       <method name="HasRaw" cname="g_mime_header_list_has_raw">
         <return-type type="gboolean" />

Modified: trunk/tests/test-headers.c
==============================================================================
--- trunk/tests/test-headers.c	(original)
+++ trunk/tests/test-headers.c	Tue Jun  3 02:42:03 2008
@@ -74,24 +74,22 @@
 {
 	const char *name, *value;
 	GMimeHeaderList *list;
-	GMimeHeaderIter *iter;
+	GMimeHeaderIter iter;
 	guint i;
 	
 	list = header_list_new ();
 	
-	iter = g_mime_header_iter_new ();
-	
 	/* make sure initial iter is valid */
 	testsuite_check ("initial iter");
 	try {
-		if (!g_mime_header_list_get_iter (list, iter))
+		if (!g_mime_header_list_get_iter (list, &iter))
 			throw (exception_new ("get_iter() failed"));
 		
-		if (!g_mime_header_iter_is_valid (iter))
+		if (!g_mime_header_iter_is_valid (&iter))
 			throw (exception_new ("invalid iter"));
 		
-		name = g_mime_header_iter_get_name (iter);
-		value = g_mime_header_iter_get_value (iter);
+		name = g_mime_header_iter_get_name (&iter);
+		value = g_mime_header_iter_get_value (&iter);
 		
 		if (strcmp (initial[0].name, name) != 0 || strcmp (initial[0].value, value) != 0)
 			throw (exception_new ("resulted in unexpected header"));
@@ -104,14 +102,14 @@
 	for (i = 1; i < G_N_ELEMENTS (initial); i++) {
 		testsuite_check ("next iter[%u]", i);
 		try {
-			if (!g_mime_header_iter_next (iter))
+			if (!g_mime_header_iter_next (&iter))
 				throw (exception_new ("failed to advance"));
 			
-			if (!g_mime_header_iter_is_valid (iter))
+			if (!g_mime_header_iter_is_valid (&iter))
 				throw (exception_new ("advanced but is invalid"));
 			
-			name = g_mime_header_iter_get_name (iter);
-			value = g_mime_header_iter_get_value (iter);
+			name = g_mime_header_iter_get_name (&iter);
+			value = g_mime_header_iter_get_value (&iter);
 			
 			if (strcmp (initial[i].name, name) != 0 ||
 			    strcmp (initial[i].value, value) != 0)
@@ -125,7 +123,7 @@
 	/* make sure trying to advance past the last header fails */
 	testsuite_check ("iter->next past end of headers");
 	try {
-		if (g_mime_header_iter_next (iter))
+		if (g_mime_header_iter_next (&iter))
 			throw (exception_new ("should not have worked"));
 		testsuite_check_passed ();
 	} catch (ex) {
@@ -137,14 +135,14 @@
 	while (i > 0) {
 		testsuite_check ("prev iter[%u]", i);
 		try {
-			if (!g_mime_header_iter_prev (iter))
+			if (!g_mime_header_iter_prev (&iter))
 				throw (exception_new ("failed to advance"));
 			
-			if (!g_mime_header_iter_is_valid (iter))
+			if (!g_mime_header_iter_is_valid (&iter))
 				throw (exception_new ("advanced but is invalid"));
 			
-			name = g_mime_header_iter_get_name (iter);
-			value = g_mime_header_iter_get_value (iter);
+			name = g_mime_header_iter_get_name (&iter);
+			value = g_mime_header_iter_get_value (&iter);
 			
 			if (strcmp (initial[i - 1].name, name) != 0 ||
 			    strcmp (initial[i - 1].value, value) != 0)
@@ -160,37 +158,36 @@
 	/* make sure trying to advance prev of the first header fails */
 	testsuite_check ("iter->prev past beginning of headers");
 	try {
-		if (g_mime_header_iter_prev (iter))
+		if (g_mime_header_iter_prev (&iter))
 			throw (exception_new ("should not have worked"));
 		testsuite_check_passed ();
 	} catch (ex) {
 		testsuite_check_failed ("iter->prev past beginning of headers: %s", ex->message);
 	} finally;
 	
-	g_mime_header_iter_free (iter);
 	g_mime_header_list_destroy (list);
 }
 
 static void
 test_iter_remove_all (void)
 {
-	GMimeHeaderIter *iter, *iter1;
 	GMimeHeaderList *list;
+	GMimeHeaderIter iter;
 	guint i = 0;
 	
 	list = header_list_new ();
-	iter = g_mime_header_iter_new ();
-	g_mime_header_list_get_iter (list, iter);
+	
+	g_mime_header_list_get_iter (list, &iter);
 	
 	testsuite_check ("removing all headers");
 	try {
-		while (g_mime_header_iter_remove (iter))
+		while (g_mime_header_iter_remove (&iter))
 			i++;
 		
 		if (i != G_N_ELEMENTS (initial))
 			throw (exception_new ("only removed %u of %u", i, G_N_ELEMENTS (initial)));
 		
-		if (g_mime_header_iter_is_valid (iter))
+		if (g_mime_header_iter_is_valid (&iter))
 			throw (exception_new ("expected invalid iter"));
 		
 		testsuite_check_passed ();
@@ -198,11 +195,11 @@
 		testsuite_check_failed ("removing all headers: %s", ex->message);
 	} finally;
 	
-	g_mime_header_list_get_iter (list, iter);
+	g_mime_header_list_get_iter (list, &iter);
 	
 	testsuite_check ("empty list iter");
 	try {
-		if (g_mime_header_iter_is_valid (iter))
+		if (g_mime_header_iter_is_valid (&iter))
 			throw (exception_new ("expected invalid iter"));
 		
 		testsuite_check_passed ();
@@ -210,130 +207,161 @@
 		testsuite_check_failed ("empty list iter: %s", ex->message);
 	} finally;
 	
-	g_mime_header_iter_free (iter);
-	
 	g_mime_header_list_destroy (list);
 }
 
 static void
 test_iter_remove (void)
 {
-	GMimeHeaderIter *iter, *iter1, *iter2, *iter3, *iter4;
+	GMimeHeaderIter iter, iter1, iter2, iter3;
 	const char *name, *value;
 	GMimeHeaderList *list;
 	guint i;
 	
 	list = header_list_new ();
-	iter1 = g_mime_header_iter_new ();
-	g_mime_header_list_get_iter (list, iter1);
+	
+	g_mime_header_list_get_iter (list, &iter1);
 	
 	testsuite_check ("iter copying");
 	try {
 		/* make iter2 point to the second header */
-		iter2 = g_mime_header_iter_copy (iter1);
-		if (!g_mime_header_iter_next (iter2))
+		g_mime_header_iter_copy_to (&iter1, &iter2);
+		if (!g_mime_header_iter_next (&iter2))
 			throw (exception_new ("iter2->next failed"));
 		
-		name = g_mime_header_iter_get_name (iter2);
-		value = g_mime_header_iter_get_value (iter2);
+		name = g_mime_header_iter_get_name (&iter2);
+		value = g_mime_header_iter_get_value (&iter2);
 		
 		if (strcmp (initial[1].name, name) != 0 ||
 		    strcmp (initial[1].value, value) != 0)
 			throw (exception_new ("iter2 resulted in unexpected header"));
 		
 		/* make iter3 point to the third header */
-		iter3 = g_mime_header_iter_copy (iter2);
-		if (!g_mime_header_iter_next (iter3))
+		g_mime_header_iter_copy_to (&iter2, &iter3);
+		if (!g_mime_header_iter_next (&iter3))
 			throw (exception_new ("iter3->next failed"));
 		
-		name = g_mime_header_iter_get_name (iter3);
-		value = g_mime_header_iter_get_value (iter3);
+		name = g_mime_header_iter_get_name (&iter3);
+		value = g_mime_header_iter_get_value (&iter3);
 		
 		if (strcmp (initial[2].name, name) != 0 ||
 		    strcmp (initial[2].value, value) != 0)
 			throw (exception_new ("iter3 resulted in unexpected header"));
 		
-		/* make iter4 point to the forth header */
-		iter4 = g_mime_header_iter_copy (iter3);
-		if (!g_mime_header_iter_next (iter4))
-			throw (exception_new ("iter4->next failed"));
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("iter copying: %s", ex->message);
+	} finally;
+	
+	testsuite_check ("remove first header");
+	try {
+		/* remove the first header */
+		g_mime_header_iter_copy_to (&iter1, &iter);
+		if (!g_mime_header_iter_remove (&iter))
+			throw (exception_new ("iter::remove() failed"));
+		
+		/* make sure iter now points to the 2nd header */
+		name = g_mime_header_iter_get_name (&iter);
+		value = g_mime_header_iter_get_value (&iter);
+		
+		if (strcmp (initial[1].name, name) != 0 ||
+		    strcmp (initial[1].value, value) != 0)
+			throw (exception_new ("iter doesn't point to 2nd header as expected"));
+		
+		/* make sure that the other iters have been invalidated */
+		if (g_mime_header_iter_is_valid (&iter1))
+			throw (exception_new ("iter::remove() iter1::isvalid() incorrect"));
+		if (g_mime_header_iter_is_valid (&iter2))
+			throw (exception_new ("iter::remove() iter2::isvalid() incorrect"));
+		if (g_mime_header_iter_is_valid (&iter3))
+			throw (exception_new ("iter::remove() iter3::isvalid() incorrect"));
+		
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("remove first header: %s", ex->message);
+	} finally;
+	
+	testsuite_check ("remove last header");
+	try {
+		/* remove the last header */
+		g_mime_header_iter_last (&iter);
+		
+		if (!g_mime_header_iter_remove (&iter))
+			throw (exception_new ("iter::remove() failed"));
+		
+		/* iter should be invalid now because it couldn't advance to a header beyond the last */
+		if (g_mime_header_iter_is_valid (&iter))
+			throw (exception_new ("iter::remove() iter is valid when it shouldn't be"));
+		
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("remove last header: %s", ex->message);
+	} finally;
+	
+	testsuite_check ("remove middle header");
+	try {
+		g_mime_header_list_get_iter (list, &iter);
 		
-		name = g_mime_header_iter_get_name (iter4);
-		value = g_mime_header_iter_get_value (iter4);
+		/* advance to a header in the middle somewhere... */
+		g_mime_header_iter_next (&iter);
+		g_mime_header_iter_next (&iter);
+		
+		/* we should now be pointing to the 3rd header (4th from the initial headers) */
+		name = g_mime_header_iter_get_name (&iter);
+		value = g_mime_header_iter_get_value (&iter);
 		
 		if (strcmp (initial[3].name, name) != 0 ||
 		    strcmp (initial[3].value, value) != 0)
-			throw (exception_new ("iter4 resulted in unexpected header"));
+			throw (exception_new ("iter doesn't point to 3rd header as expected"));
+		
+		/* remove it */
+		if (!g_mime_header_iter_remove (&iter))
+			throw (exception_new ("iter::remove() failed"));
+		
+		/* make sure the iter is still valid */
+		if (!g_mime_header_iter_is_valid (&iter))
+			throw (exception_new ("iter::remove() iter isn't valid when it should be"));
+		
+		/* make sure iter now points to the 4th header */
+		name = g_mime_header_iter_get_name (&iter);
+		value = g_mime_header_iter_get_value (&iter);
+		
+		if (strcmp (initial[4].name, name) != 0 ||
+		    strcmp (initial[4].value, value) != 0)
+			throw (exception_new ("iter doesn't point to 4th header as expected"));
 		
 		testsuite_check_passed ();
 	} catch (ex) {
-		testsuite_check_failed ("iter copying: %s", ex->message);
+		testsuite_check_failed ("remove first header: %s", ex->message);
 	} finally;
 	
-	testsuite_check ("iter remove");
+	testsuite_check ("resulting lists match");
 	try {
-		/* remove the third header */
-		iter = g_mime_header_iter_copy (iter3);
-		if (!g_mime_header_iter_remove (iter)) {
-			g_mime_header_iter_free (iter);
-			throw (exception_new ("iter::remove(3) failed"));
-		}
-		
-		/* make sure iter now points to the same header as iter4 */
-		if (!g_mime_header_iter_equal (iter, iter4)) {
-			g_mime_header_iter_free (iter);
-			throw (exception_new ("iter::remove (3) iter::equal(4) failed"));
-		}
-		
-		g_mime_header_iter_free (iter);
-		
-		/* make sure that iter3 is invalid */
-		if (g_mime_header_iter_is_valid (iter3))
-			throw (exception_new ("iter::remove (3) iter3::isvalid() incorrect"));
-		
-		/* make sure that iter1, iter2, and iter4 are still valid */
-		if (!g_mime_header_iter_is_valid (iter1))
-			throw (exception_new ("iter::remove (3) iter1::isvalid() incorrect"));
-		if (!g_mime_header_iter_is_valid (iter2))
-			throw (exception_new ("iter::remove (3) iter2::isvalid() incorrect"));
-		if (!g_mime_header_iter_is_valid (iter4))
-			throw (exception_new ("iter::remove (3) iter4::isvalid() incorrect"));
+		g_mime_header_list_get_iter (list, &iter);
+		i = 1;
 		
-		/* remove the first header */
-		iter = g_mime_header_iter_copy (iter1);
-		if (!g_mime_header_iter_remove (iter)) {
-			g_mime_header_iter_free (iter);
-			throw (exception_new ("iter::remove(1) failed"));
-		}
-		
-		/* make sure iter now points to the same header as iter2 */
-		if (!g_mime_header_iter_equal (iter, iter2)) {
-			g_mime_header_iter_free (iter);
-			throw (exception_new ("iter::remove (1) iter::equal(2) failed"));
-		}
-		
-		g_mime_header_iter_free (iter);
-		
-		/* make sure that iter1 is invalid */
-		if (g_mime_header_iter_is_valid (iter1))
-			throw (exception_new ("iter::remove (1) iter1::isvalid() incorrect"));
-		
-		/* make sure that iter2 and iter4 are still valid */
-		if (!g_mime_header_iter_is_valid (iter2))
-			throw (exception_new ("iter::remove (1) iter2::isvalid() incorrect"));
-		if (!g_mime_header_iter_is_valid (iter4))
-			throw (exception_new ("iter::remove (1) iter4::isvalid() incorrect"));
+		do {
+			name = g_mime_header_iter_get_name (&iter);
+			value = g_mime_header_iter_get_value (&iter);
+			
+			if (i == 3)
+				i++;
+			
+			if (strcmp (initial[i].name, name) != 0 ||
+			    strcmp (initial[i].value, value) != 0)
+				throw (exception_new ("iter vs array mismatch @ index %u", i));
+			
+			i++;
+		} while (g_mime_header_iter_next (&iter));
+		
+		if (++i != G_N_ELEMENTS (initial))
+			throw (exception_new ("iter didn't have as many headers as expected"));
 		
 		testsuite_check_passed ();
 	} catch (ex) {
-		testsuite_check_failed ("iter remove: %s", ex->message);
+		testsuite_check_failed ("resulting lists match: %s", ex->message);
 	} finally;
 	
-	g_mime_header_iter_free (iter1);
-	g_mime_header_iter_free (iter2);
-	g_mime_header_iter_free (iter3);
-	g_mime_header_iter_free (iter4);
-	
 	g_mime_header_list_destroy (list);
 }
 
@@ -351,7 +379,7 @@
 	test_iter_remove_all ();
 	testsuite_end ();
 	
-	testsuite_start ("removing headers");
+	testsuite_start ("removing individual headers");
 	test_iter_remove ();
 	testsuite_end ();
 	



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