gmime r1311 - in trunk: . docs/reference gmime mono tests



Author: fejj
Date: Sat May 31 15:23:39 2008
New Revision: 1311
URL: http://svn.gnome.org/viewvc/gmime?rev=1311&view=rev

Log:
2008-05-31  Jeffrey Stedfast  <fejj novell com>

	* tests/test-headers.c: New set of unit tests for GMimeHeaderIter.

	* gmime/gmime-header.c (g_mime_header_iter_equal): New method to
	check if two iters are equal.
	(g_mime_header_iter_first): New method to update @iter to point to
	the first header.
	(g_mime_header_iter_last): New method to update @iter to point to
	the last header.
	(g_mime_header_iter_next): Fixed.
	(g_mime_header_iter_prev): Fixed.
	(g_mime_header_iter_remove): Invalidate all other iters currently
	pointing to the same header as @iter.



Added:
   trunk/mono/HeaderList.custom
   trunk/tests/test-headers.c
Removed:
   trunk/mono/Header.custom
Modified:
   trunk/ChangeLog
   trunk/docs/reference/gmime-sections.txt
   trunk/gmime/gmime-header.c
   trunk/gmime/gmime-header.h
   trunk/mono/GMime.metadata
   trunk/mono/Makefile.am
   trunk/mono/gmime-api.raw
   trunk/tests/Makefile.am

Modified: trunk/docs/reference/gmime-sections.txt
==============================================================================
--- trunk/docs/reference/gmime-sections.txt	(original)
+++ trunk/docs/reference/gmime-sections.txt	Sat May 31 15:23:39 2008
@@ -575,6 +575,9 @@
 GMimeHeaderWriter
 g_mime_header_iter_copy
 g_mime_header_iter_free
+g_mime_header_iter_equal
+g_mime_header_iter_first
+g_mime_header_iter_last
 g_mime_header_iter_next
 g_mime_header_iter_prev
 g_mime_header_iter_is_valid

Modified: trunk/gmime/gmime-header.c
==============================================================================
--- trunk/gmime/gmime-header.c	(original)
+++ trunk/gmime/gmime-header.c	Sat May 31 15:23:39 2008
@@ -75,10 +75,11 @@
 	GMimeHeader *cursor;
 };
 
-
+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);
 
+
 /**
  * g_mime_header_new:
  * @name: header name
@@ -165,6 +166,26 @@
 
 
 /**
+ * g_mime_header_iter_equal:
+ * @iter1: a #GMimeHeaderIter
+ * @iter2: a #GMimeHeaderIter
+ *
+ * Check that @iter1 and @iter2 reference the same header.
+ *
+ * Returns %TRUE if @iter1 and @iter2 refer to the same header or
+ * %FALSE otherwise.
+ **/
+gboolean
+g_mime_header_iter_equal (GMimeHeaderIter *iter1, GMimeHeaderIter *iter2)
+{
+	g_return_val_if_fail (iter1 != NULL, FALSE);
+	g_return_val_if_fail (iter2 != NULL, FALSE);
+	
+	return iter1->cursor == iter2->cursor;
+}
+
+
+/**
  * g_mime_header_iter_is_valid:
  * @iter: a #GMimeHeaderIter
  *
@@ -184,6 +205,64 @@
 
 
 /**
+ * g_mime_header_iter_first:
+ * @iter: a #GMimeHeaderIter
+ *
+ * Updates @iter to point to the first header.
+ *
+ * Returns %TRUE on success or %FALSE otherwise.
+ **/
+gboolean
+g_mime_header_iter_first (GMimeHeaderIter *iter)
+{
+	GMimeHeader *first;
+	
+	g_return_val_if_fail (iter != NULL, FALSE);
+	
+	/* make sure we can actually do as requested */
+	if (!iter->headers)
+		return FALSE;
+	
+	first = (GMimeHeader *) iter->headers->list.head;
+	if (!first->next)
+		return FALSE;
+	
+	iter->cursor = first;
+	
+	return TRUE;
+}
+
+
+/**
+ * g_mime_header_iter_last:
+ * @iter: a #GMimeHeaderIter
+ *
+ * Updates @iter to point to the last header.
+ *
+ * Returns %TRUE on success or %FALSE otherwise.
+ **/
+gboolean
+g_mime_header_iter_last (GMimeHeaderIter *iter)
+{
+	GMimeHeader *last;
+	
+	g_return_val_if_fail (iter != NULL, FALSE);
+	
+	/* make sure we can actually do as requested */
+	if (!iter->headers)
+		return FALSE;
+	
+	last = (GMimeHeader *) iter->headers->list.tailpred;
+	if (!last->next)
+		return FALSE;
+	
+	iter->cursor = last;
+	
+	return TRUE;
+}
+
+
+/**
  * g_mime_header_iter_next:
  * @iter: a #GMimeHeaderIter
  *
@@ -194,19 +273,27 @@
 gboolean
 g_mime_header_iter_next (GMimeHeaderIter *iter)
 {
+	GMimeHeader *next;
+	
 	g_return_val_if_fail (iter != NULL, FALSE);
 	
+	/* make sure current cursor is valid */
 	if (!iter->cursor || !iter->cursor->next)
 		return FALSE;
 	
-	iter->cursor = iter->cursor->next;
+	/* make sure next item is valid */
+	next = iter->cursor->next;
+	if (!next->next)
+		return FALSE;
+	
+	iter->cursor = next;
 	
-	return iter->next != NULL;
+	return TRUE;
 }
 
 
 /**
- * g_mime_header_iter_next:
+ * g_mime_header_iter_prev:
  * @iter: a #GMimeHeaderIter
  *
  * Advances to the previous header.
@@ -216,14 +303,22 @@
 gboolean
 g_mime_header_iter_prev (GMimeHeaderIter *iter)
 {
+	GMimeHeader *prev;
+	
 	g_return_val_if_fail (iter != NULL, FALSE);
 	
+	/* make sure current cursor is valid */
 	if (!iter->cursor || !iter->cursor->prev)
 		return FALSE;
 	
-	iter->cursor = iter->cursor->prev;
+	/* make sure prev item is valid */
+	prev = iter->cursor->prev;
+	if (!prev->prev)
+		return FALSE;
 	
-	return iter->prev != NULL;
+	iter->cursor = prev;
+	
+	return TRUE;
 }
 
 
@@ -238,7 +333,7 @@
 gint64
 g_mime_header_iter_get_offset (GMimeHeaderIter *iter)
 {
-	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (iter != NULL, -1);
 	
 	if (!iter->cursor || !iter->cursor->next)
 		return -1;
@@ -324,9 +419,8 @@
 gboolean
 g_mime_header_iter_remove (GMimeHeaderIter *iter)
 {
-	GMimeHeader *header, *next;
+	GMimeHeader *cursor, *header, *next;
 	GMimeHeaderList *headers;
-	char *name;
 	
 	g_return_val_if_fail (iter != NULL, FALSE);
 	
@@ -334,21 +428,21 @@
 		return FALSE;
 	
 	/* save iter state */
-	next = iter->cursor->next;
-	name = iter->cursor->name;
 	headers = iter->headers;
+	cursor = iter->cursor;
+	next = cursor->next;
 	
-	if (!(header = g_hash_table_lookup (headers->hash, name)))
+	if (!(header = g_hash_table_lookup (headers->hash, cursor->name)))
 		return FALSE;
 	
-	if (iter->cursor == header) {
+	if (cursor == header) {
 		/* update the header lookup table */
-		GMimeHeader *node = iter->cursor->next;
+		GMimeHeader *node = next;
 		
-		g_hash_table_remove (headers->hash, name);
+		g_hash_table_remove (headers->hash, cursor->name);
 		
 		while (node->next) {
-			if (!g_ascii_strcasecmp (node->name, name)) {
+			if (!g_ascii_strcasecmp (node->name, cursor->name)) {
 				/* enter this node into the lookup table */
 				g_hash_table_insert (headers->hash, node->name, node);
 				break;
@@ -359,8 +453,9 @@
 	}
 	
 	/* remove/free the header */
-	list_unlink ((ListNode *) iter->cursor);
-	g_mime_header_free (iter->cursor);
+	g_mime_header_list_invalidate_iters (iter->headers, cursor);
+	list_unlink ((ListNode *) cursor);
+	g_mime_header_free (cursor);
 	
 	/* restore iter state */
 	iter->headers = headers;
@@ -391,8 +486,12 @@
 		if (!header || iter->cursor == header) {
 			/* invalidate this iter */
 			list_unlink ((ListNode *) iter);
-			iter->headers = NULL;
 			iter->cursor = NULL;
+			
+			if (header == NULL) {
+				/* invalidating because HeaderList is being destroyed */
+				iter->headers = NULL;
+			}
 		}
 		
 		iter = next;

Modified: trunk/gmime/gmime-header.h
==============================================================================
--- trunk/gmime/gmime-header.h	(original)
+++ trunk/gmime/gmime-header.h	Sat May 31 15:23:39 2008
@@ -37,8 +37,13 @@
 GMimeHeaderIter *g_mime_header_iter_copy (GMimeHeaderIter *iter);
 void g_mime_header_iter_free (GMimeHeaderIter *iter);
 
+gboolean g_mime_header_iter_equal (GMimeHeaderIter *iter1, GMimeHeaderIter *iter2);
+
 gboolean g_mime_header_iter_is_valid (GMimeHeaderIter *iter);
 
+gboolean g_mime_header_iter_first (GMimeHeaderIter *iter);
+gboolean g_mime_header_iter_last (GMimeHeaderIter *iter);
+
 gboolean g_mime_header_iter_next (GMimeHeaderIter *iter);
 gboolean g_mime_header_iter_prev (GMimeHeaderIter *iter);
 

Modified: trunk/mono/GMime.metadata
==============================================================================
--- trunk/mono/GMime.metadata	(original)
+++ trunk/mono/GMime.metadata	Sat May 31 15:23:39 2008
@@ -55,10 +55,6 @@
   <remove-node path="/api/namespace/object[ cname='GMimeObject']/method[ cname='g_mime_object_set_content_disposition_parameter']"/>
 
   <!-- Remove duplicate functionality from GMimeMessage -->
-  <remove-node path="/api/namespace/object[ cname='GMimeMessage']/method[ cname='g_mime_message_add_header']"/>
-  <remove-node path="/api/namespace/object[ cname='GMimeMessage']/method[ cname='g_mime_message_get_header']"/>
-  <remove-node path="/api/namespace/object[ cname='GMimeMessage']/method[ cname='g_mime_message_set_header']"/>
-  <remove-node path="/api/namespace/object[ cname='GMimeMessage']/method[ cname='g_mime_message_get_headers']"/>
   <remove-node path="/api/namespace/object[ cname='GMimeMessage']/method[ cname='g_mime_message_get_date']"/>
   <remove-node path="/api/namespace/object[ cname='GMimeMessage']/method[ cname='g_mime_message_set_date']"/>
 
@@ -125,7 +121,8 @@
   <attr path="/api/namespace/struct[ name='References']/method[ name='Decode']" name="name">Parse</attr>
 
   <!-- Hide some problematic and nonsensical elements -->
-  <attr path="/api/namespace/struct[ cname='GMimeHeader']/method[ name='SetRaw']" name="hidden">true</attr>
+  <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/object[ cname='GMimeStream']/method[ name='Read']" name="hidden">trye</attr>
   <attr path="/api/namespace/object[ cname='GMimeStreamMem']/constructor[ cname='g_mime_stream_mem_new_with_byte_array']" name="hidden">true</attr>
   <attr path="/api/namespace/object[ cname='GMimeStreamFile']" name="hidden">true</attr>

Added: trunk/mono/HeaderList.custom
==============================================================================
--- (empty file)
+++ trunk/mono/HeaderList.custom	Sat May 31 15:23:39 2008
@@ -0,0 +1,8 @@
+public StreamWrapper Stream {
+	get {
+		GMime.StreamMem mem_stream = new GMime.StreamMem ();
+		this.WriteToStream (mem_stream);
+		mem_stream.Seek (0);
+		return new StreamWrapper (mem_stream);
+	}
+}

Modified: trunk/mono/Makefile.am
==============================================================================
--- trunk/mono/Makefile.am	(original)
+++ trunk/mono/Makefile.am	Sat May 31 15:23:39 2008
@@ -29,7 +29,7 @@
 customs = 				\
 	DataWrapper.custom		\
 	Global.custom			\
-	Header.custom			\
+	HeaderList.custom		\
 	Message.custom			\
 	Object.custom			\
 	Stream.custom
@@ -37,7 +37,7 @@
 build_customs = 			\
 	$(srcdir)/DataWrapper.custom	\
 	$(srcdir)/Global.custom		\
-	$(srcdir)/Header.custom		\
+	$(srcdir)/HeaderList.custom	\
 	$(srcdir)/Message.custom	\
 	$(srcdir)/Object.custom		\
 	$(srcdir)/Stream.custom

Modified: trunk/mono/gmime-api.raw
==============================================================================
--- trunk/mono/gmime-api.raw	(original)
+++ trunk/mono/gmime-api.raw	Sat May 31 15:23:39 2008
@@ -703,9 +703,6 @@
           <parameter type="const-char*" name="header" />
         </parameters>
       </method>
-      <method name="GetHeaders" cname="g_mime_message_get_headers">
-        <return-type type="char*" />
-      </method>
       <method name="GetMessageId" cname="g_mime_message_get_message_id">
         <return-type type="const-char*" />
       </method>
@@ -1034,7 +1031,7 @@
     <object name="Object" cname="GMimeObject" parent="GObject">
       <field name="Disposition" cname="disposition" type="GMimeContentDisposition*" />
       <field name="ContentType" cname="content_type" type="GMimeContentType*" />
-      <field name="Headers" cname="headers" type="GMimeHeader*" />
+      <field name="Headers" cname="headers" type="GMimeHeaderList*" />
       <field name="ContentId" cname="content_id" type="char*" />
       <virtual_method name="Init" cname="init">
         <return-type type="void" />
@@ -1042,7 +1039,15 @@
           <parameter type="GMimeObject*" name="object" />
         </parameters>
       </virtual_method>
-      <virtual_method name="AddHeader" cname="add_header">
+      <virtual_method name="PrependHeader" cname="prepend_header">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GMimeObject*" name="object" />
+          <parameter type="const-char*" name="header" />
+          <parameter type="const-char*" name="value" />
+        </parameters>
+      </virtual_method>
+      <virtual_method name="AppendHeader" cname="append_header">
         <return-type type="void" />
         <parameters>
           <parameter type="GMimeObject*" name="object" />
@@ -1059,7 +1064,7 @@
         </parameters>
       </virtual_method>
       <virtual_method name="RemoveHeader" cname="remove_header">
-        <return-type type="void" />
+        <return-type type="gboolean" />
         <parameters>
           <parameter type="GMimeObject*" name="object" />
           <parameter type="const-char*" name="header" />
@@ -1085,7 +1090,7 @@
           <parameter type="GMimeStream*" name="stream" />
         </parameters>
       </virtual_method>
-      <method name="AddHeader" cname="g_mime_object_add_header">
+      <method name="AppendHeader" cname="g_mime_object_append_header">
         <return-type type="void" />
         <parameters>
           <parameter type="const-char*" name="header" />
@@ -1122,6 +1127,9 @@
           <parameter type="const-char*" name="header" />
         </parameters>
       </method>
+      <method name="GetHeaderList" cname="g_mime_object_get_header_list">
+        <return-type type="const-GMimeHeaderList*" />
+      </method>
       <method name="GetHeaders" cname="g_mime_object_get_headers">
         <return-type type="char*" />
       </method>
@@ -1134,6 +1142,13 @@
           <parameter type="const-char*" name="subtype" />
         </parameters>
       </constructor>
+      <method name="PrependHeader" cname="g_mime_object_prepend_header">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="const-char*" name="header" />
+          <parameter type="const-char*" name="value" />
+        </parameters>
+      </method>
       <method name="RegisterType" cname="g_mime_object_register_type" shared="true">
         <return-type type="void" />
         <parameters>
@@ -1143,7 +1158,7 @@
         </parameters>
       </method>
       <method name="RemoveHeader" cname="g_mime_object_remove_header">
-        <return-type type="void" />
+        <return-type type="gboolean" />
         <parameters>
           <parameter type="const-char*" name="header" />
         </parameters>
@@ -1193,6 +1208,12 @@
           <parameter type="const-char*" name="value" />
         </parameters>
       </method>
+      <method name="SetHeaderList" cname="g_mime_object_set_header_list">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GMimeHeaderList*" name="headers" />
+        </parameters>
+      </method>
       <method name="ToString" cname="g_mime_object_to_string">
         <return-type type="char*" />
       </method>
@@ -2104,71 +2125,121 @@
         </parameters>
       </method>
     </struct>
-    <struct name="Header" cname="GMimeHeader" opaque="true">
-      <method name="Add" cname="g_mime_header_add">
+    <struct name="HeaderIter" cname="GMimeHeaderIter" opaque="true">
+      <method name="Copy" cname="g_mime_header_iter_copy">
+        <return-type type="GMimeHeaderIter*" owned="true" />
+      </method>
+      <method name="Equal" cname="g_mime_header_iter_equal">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="GMimeHeaderIter*" name="iter2" />
+        </parameters>
+      </method>
+      <method name="First" cname="g_mime_header_iter_first">
+        <return-type type="gboolean" />
+      </method>
+      <method name="Free" cname="g_mime_header_iter_free">
+        <return-type type="void" />
+      </method>
+      <method name="GetName" cname="g_mime_header_iter_get_name">
+        <return-type type="const-char*" />
+      </method>
+      <method name="GetOffset" cname="g_mime_header_iter_get_offset">
+        <return-type type="gint64" />
+      </method>
+      <method name="GetValue" cname="g_mime_header_iter_get_value">
+        <return-type type="const-char*" />
+      </method>
+      <method name="IsValid" cname="g_mime_header_iter_is_valid">
+        <return-type type="gboolean" />
+      </method>
+      <method name="Last" cname="g_mime_header_iter_last">
+        <return-type type="gboolean" />
+      </method>
+      <method name="Next" cname="g_mime_header_iter_next">
+        <return-type type="gboolean" />
+      </method>
+      <method name="Prev" cname="g_mime_header_iter_prev">
+        <return-type type="gboolean" />
+      </method>
+      <method name="Remove" cname="g_mime_header_iter_remove">
+        <return-type type="gboolean" />
+      </method>
+      <method name="SetValue" cname="g_mime_header_iter_set_value">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="const-char*" name="value" />
+        </parameters>
+      </method>
+    </struct>
+    <struct name="HeaderList" cname="GMimeHeaderList" opaque="true">
+      <method name="Append" cname="g_mime_header_list_append">
         <return-type type="void" />
         <parameters>
           <parameter type="const-char*" name="name" />
           <parameter type="const-char*" name="value" />
         </parameters>
       </method>
-      <method name="Destroy" cname="g_mime_header_destroy">
+      <method name="Destroy" cname="g_mime_header_list_destroy">
         <return-type type="void" />
       </method>
-      <method name="Foreach" cname="g_mime_header_foreach">
+      <method name="Foreach" cname="g_mime_header_list_foreach">
         <return-type type="void" />
         <parameters>
           <parameter type="GMimeHeaderForeachFunc" name="func" />
           <parameter type="gpointer" name="user_data" />
         </parameters>
       </method>
-      <method name="Get" cname="g_mime_header_get">
+      <method name="Get" cname="g_mime_header_list_get">
         <return-type type="const-char*" />
         <parameters>
           <parameter type="const-char*" name="name" />
         </parameters>
       </method>
-      <method name="HasRaw" cname="g_mime_header_has_raw">
+      <method name="GetIter" cname="g_mime_header_list_get_iter">
+        <return-type type="GMimeHeaderIter*" />
+      </method>
+      <method name="HasRaw" cname="g_mime_header_list_has_raw">
         <return-type type="gboolean" />
       </method>
-      <constructor cname="g_mime_header_new" />
-      <method name="Prepend" cname="g_mime_header_prepend">
+      <constructor cname="g_mime_header_list_new" />
+      <method name="Prepend" cname="g_mime_header_list_prepend">
         <return-type type="void" />
         <parameters>
           <parameter type="const-char*" name="name" />
           <parameter type="const-char*" name="value" />
         </parameters>
       </method>
-      <method name="RegisterWriter" cname="g_mime_header_register_writer">
+      <method name="RegisterWriter" cname="g_mime_header_list_register_writer">
         <return-type type="void" />
         <parameters>
           <parameter type="const-char*" name="name" />
           <parameter type="GMimeHeaderWriter" name="writer" />
         </parameters>
       </method>
-      <method name="Remove" cname="g_mime_header_remove">
-        <return-type type="void" />
+      <method name="Remove" cname="g_mime_header_list_remove">
+        <return-type type="gboolean" />
         <parameters>
           <parameter type="const-char*" name="name" />
         </parameters>
       </method>
-      <method name="Set" cname="g_mime_header_set">
+      <method name="Set" cname="g_mime_header_list_set">
         <return-type type="void" />
         <parameters>
           <parameter type="const-char*" name="name" />
           <parameter type="const-char*" name="value" />
         </parameters>
       </method>
-      <method name="SetRaw" cname="g_mime_header_set_raw">
+      <method name="SetRaw" cname="g_mime_header_list_set_raw">
         <return-type type="void" />
         <parameters>
           <parameter type="const-char*" name="raw" />
         </parameters>
       </method>
-      <method name="ToString" cname="g_mime_header_to_string">
+      <method name="ToString" cname="g_mime_header_list_to_string">
         <return-type type="char*" />
       </method>
-      <method name="WriteToStream" cname="g_mime_header_write_to_stream">
+      <method name="WriteToStream" cname="g_mime_header_list_write_to_stream">
         <return-type type="ssize_t" />
         <parameters>
           <parameter type="GMimeStream*" name="stream" />

Modified: trunk/tests/Makefile.am
==============================================================================
--- trunk/tests/Makefile.am	(original)
+++ trunk/tests/Makefile.am	Sat May 31 15:23:39 2008
@@ -20,6 +20,7 @@
 	test-iconv	\
 	test-streams	\
 	test-cat	\
+	test-headers	\
 	test-mbox	\
 	test-mime	\
 	test-pgp	\
@@ -46,6 +47,11 @@
 test_mime_DEPENDENCIES = $(DEPS)
 test_mime_LDADD = $(LDADDS)
 
+test_headers_SOURCES = test-headers.c testsuite.c testsuite.h
+test_headers_LDFLAGS = 
+test_headers_DEPENDENCIES = $(DEPS)
+test_headers_LDADD = $(LDADDS)
+
 test_parser_SOURCES = test-parser.c
 test_parser_LDFLAGS = 
 test_parser_DEPENDENCIES = $(DEPS)

Added: trunk/tests/test-headers.c
==============================================================================
--- (empty file)
+++ trunk/tests/test-headers.c	Sat May 31 15:23:39 2008
@@ -0,0 +1,357 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2008 Jeffrey Stedfast
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <gmime/gmime.h>
+
+#include "testsuite.h"
+
+extern int verbose;
+
+#define d(x)
+#define v(x) if (verbose > 3) x
+
+typedef struct {
+	const char *name;
+	const char *value;
+} Header;
+
+static Header initial[] = {
+	{ "Received",   "first received header"            },
+	{ "Received",   "second received header"           },
+	{ "Received",   "third received header"            },
+	{ "Date",       "Sat, 31 May 2008 08:56:43 EST"    },
+	{ "From",       "someone somewhere com"            },
+	{ "Sender",     "someoneelse somewhere com"        },
+	{ "To",         "coworker somewhere com"           },
+	{ "Subject",    "hey, check this out"              },
+	{ "Message-Id", "<136734928 123728 localhost com>" },
+};
+
+static GMimeHeaderList *
+header_list_new (void)
+{
+	GMimeHeaderList *list;
+	guint i;
+	
+	list = g_mime_header_list_new ();
+	for (i = 0; i < G_N_ELEMENTS (initial); i++)
+		g_mime_header_list_append (list, initial[i].name, initial[i].value);
+	
+	return list;
+}
+
+static void
+test_iter_forward_back (void)
+{
+	const char *name, *value;
+	GMimeHeaderList *list;
+	GMimeHeaderIter *iter;
+	guint i;
+	
+	list = header_list_new ();
+	iter = g_mime_header_list_get_iter (list);
+	
+	/* make sure initial iter is valid */
+	testsuite_check ("initial iter");
+	try {
+		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);
+		
+		if (strcmp (initial[0].name, name) != 0 || strcmp (initial[0].value, value) != 0)
+			throw (exception_new ("resulted in unexpected header"));
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("initial iter: %s", ex->message);
+	} finally;
+	
+	/* make sure iter->next works as expected */
+	for (i = 1; i < G_N_ELEMENTS (initial); i++) {
+		testsuite_check ("next iter[%u]", i);
+		try {
+			if (!g_mime_header_iter_next (iter))
+				throw (exception_new ("failed to advance"));
+			
+			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);
+			
+			if (strcmp (initial[i].name, name) != 0 ||
+			    strcmp (initial[i].value, value) != 0)
+				throw (exception_new ("resulted in unexpected header"));
+			testsuite_check_passed ();
+		} catch (ex) {
+			testsuite_check_failed ("next iter[%u]: %s", i, ex->message);
+		} finally;
+	}
+	
+	/* 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))
+			throw (exception_new ("should not have worked"));
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("iter->next past end of headers: %s", ex->message);
+	} finally;
+	
+	/* make sure iter->prev works as expected */
+	i--;
+	while (i > 0) {
+		testsuite_check ("prev iter[%u]", i);
+		try {
+			if (!g_mime_header_iter_prev (iter))
+				throw (exception_new ("failed to advance"));
+			
+			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);
+			
+			if (strcmp (initial[i - 1].name, name) != 0 ||
+			    strcmp (initial[i - 1].value, value) != 0)
+				throw (exception_new ("resulted in unexpected header"));
+			testsuite_check_passed ();
+		} catch (ex) {
+			testsuite_check_failed ("prev iter[%u]: %s", i, ex->message);
+		} finally;
+		
+		i--;
+	}
+	
+	/* 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))
+			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;
+	guint i = 0;
+	
+	list = header_list_new ();
+	iter = g_mime_header_list_get_iter (list);
+	
+	testsuite_check ("removing all headers");
+	try {
+		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))
+			throw (exception_new ("expected invalid iter"));
+		
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("removing all headers: %s", ex->message);
+	} finally;
+	
+	g_mime_header_iter_free (iter);
+	
+	iter = g_mime_header_list_get_iter (list);
+	
+	testsuite_check ("empty list iter");
+	try {
+		if (g_mime_header_iter_is_valid (iter))
+			throw (exception_new ("expected invalid iter"));
+		
+		testsuite_check_passed ();
+	} catch (ex) {
+		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;
+	const char *name, *value;
+	GMimeHeaderList *list;
+	guint i;
+	
+	list = header_list_new ();
+	iter1 = g_mime_header_list_get_iter (list);
+	
+	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))
+			throw (exception_new ("iter2->next failed"));
+		
+		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))
+			throw (exception_new ("iter3->next failed"));
+		
+		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"));
+		
+		name = g_mime_header_iter_get_name (iter4);
+		value = g_mime_header_iter_get_value (iter4);
+		
+		if (strcmp (initial[3].name, name) != 0 ||
+		    strcmp (initial[3].value, value) != 0)
+			throw (exception_new ("iter4 resulted in unexpected header"));
+		
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("iter copying: %s", ex->message);
+	} finally;
+	
+	testsuite_check ("iter remove");
+	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"));
+		
+		/* 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"));
+		
+		testsuite_check_passed ();
+	} catch (ex) {
+		testsuite_check_failed ("iter remove: %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);
+}
+
+int main (int argc, char **argv)
+{
+	g_mime_init (0);
+	
+	testsuite_init (argc, argv);
+	
+	testsuite_start ("iterating forward and backward");
+	test_iter_forward_back ();
+	testsuite_end ();
+	
+	testsuite_start ("removing all headers");
+	test_iter_remove_all ();
+	testsuite_end ();
+	
+	testsuite_start ("removing headers");
+	test_iter_remove ();
+	testsuite_end ();
+	
+	g_mime_shutdown ();
+	
+	return testsuite_exit ();
+}



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