[gmime] Modified GMimeHeader[List] to subclass GObject



commit 95f8c4b239d660baac08893b30b47d2010810d42
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Thu Mar 16 09:19:52 2017 -0400

    Modified GMimeHeader[List] to subclass GObject

 TODO                              |    2 -
 docs/reference/gmime-sections.txt |   21 ++-
 gmime/gmime-certificate.c         |    7 +-
 gmime/gmime-header.c              |  373 ++++++++++++++++++++++---------------
 gmime/gmime-header.h              |   66 ++++++-
 gmime/gmime-internal.h            |    1 -
 gmime/gmime-message.c             |    8 +-
 gmime/gmime-object.c              |   22 +--
 tests/test-headers.c              |    6 +-
 9 files changed, 325 insertions(+), 181 deletions(-)
---
diff --git a/TODO b/TODO
index af43821..7a3ef3b 100644
--- a/TODO
+++ b/TODO
@@ -8,8 +8,6 @@ GMime 3.0 Planning:
 
 - Convert GMimeParam[List] into GObjects
 
-- Convert GMimeHeader[List] into GObjects
-
 - Rewrite GMimeReferences into a GObject and split into its own file
 
 - Add g_mime_utils_header_decode_[text,phrase]() variants that also return charset/lang values?
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index 7d6f9c1..9daef90 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -603,7 +603,6 @@ g_mime_header_get_value
 g_mime_header_set_value
 g_mime_header_write_to_stream
 g_mime_header_list_new
-g_mime_header_list_free
 g_mime_header_list_get_count
 g_mime_header_list_clear
 g_mime_header_list_contains
@@ -617,6 +616,26 @@ g_mime_header_list_remove_at
 g_mime_header_list_register_writer
 g_mime_header_list_write_to_stream
 g_mime_header_list_to_string
+
+<SUBSECTION Private>
+g_mime_header_get_type
+g_mime_header_list_get_type
+
+<SUBSECTION Standard>
+GMIME_HEADER
+GMIME_IS_HEADER
+GMIME_TYPE_HEADER
+GMIME_HEADER_CLASS
+GMIME_IS_HEADER_CLASS
+GMIME_HEADER_GET_CLASS
+GMimeHeaderClass
+GMIME_HEADER_LIST
+GMIME_IS_HEADER_LIST
+GMIME_TYPE_HEADER_LIST
+GMIME_HEADER_LIST_CLASS
+GMIME_IS_HEADER_LIST_CLASS
+GMIME_HEADER_LIST_GET_CLASS
+GMimeHeaderListClass
 </SECTION>
 
 <SECTION>
diff --git a/gmime/gmime-certificate.c b/gmime/gmime-certificate.c
index 71e1752..cd4adc9 100644
--- a/gmime/gmime-certificate.c
+++ b/gmime/gmime-certificate.c
@@ -550,13 +550,10 @@ static void
 g_mime_certificate_list_finalize (GObject *object)
 {
        GMimeCertificateList *list = (GMimeCertificateList *) object;
-       GMimeCertificate *cert;
        guint i;
        
-       for (i = 0; i < list->array->len; i++) {
-               cert = (GMimeCertificate *) list->array->pdata[i];
-               g_object_unref (cert);
-       }
+       for (i = 0; i < list->array->len; i++)
+               g_object_unref (list->array->pdata[i]);
        
        g_ptr_array_free (list->array, TRUE);
        
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index 8b26153..5c72238 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -46,21 +46,72 @@
  * values.
  **/
 
-struct _GMimeHeader {
-       GMimeHeaderList *list;
-       gint64 offset;
-       char *name;
-       char *value;
-       char *raw_value;
-};
-
-struct _GMimeHeaderList {
-       GMimeParserOptions *options;
-       GHashTable *writers;
-       GMimeEvent *changed;
-       GHashTable *hash;
-       GPtrArray *list;
-};
+
+static void g_mime_header_class_init (GMimeHeaderClass *klass);
+static void g_mime_header_init (GMimeHeader *cert, GMimeHeaderClass *klass);
+static void g_mime_header_finalize (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+
+
+GType
+g_mime_header_get_type (void)
+{
+       static GType type = 0;
+       
+       if (!type) {
+               static const GTypeInfo info = {
+                       sizeof (GMimeHeaderClass),
+                       NULL, /* base_class_init */
+                       NULL, /* base_class_finalize */
+                       (GClassInitFunc) g_mime_header_class_init,
+                       NULL, /* class_finalize */
+                       NULL, /* class_data */
+                       sizeof (GMimeHeader),
+                       0,    /* n_preallocs */
+                       (GInstanceInitFunc) g_mime_header_init,
+               };
+               
+               type = g_type_register_static (G_TYPE_OBJECT, "GMimeHeader", &info, 0);
+       }
+       
+       return type;
+}
+
+static void
+g_mime_header_class_init (GMimeHeaderClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       
+       parent_class = g_type_class_ref (G_TYPE_OBJECT);
+       
+       object_class->finalize = g_mime_header_finalize;
+}
+
+static void
+g_mime_header_init (GMimeHeader *header, GMimeHeaderClass *klass)
+{
+       header->changed = g_mime_event_new (header);
+       header->raw_value = NULL;
+       header->raw_name = NULL;
+       header->value = NULL;
+       header->name = NULL;
+       header->offset = -1;
+}
+
+static void
+g_mime_header_finalize (GObject *object)
+{
+       GMimeHeader *header = (GMimeHeader *) object;
+       
+       g_mime_event_free (header->changed);
+       g_free (header->raw_value);
+       g_free (header->raw_name);
+       g_free (header->value);
+       g_free (header->name);
+       
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
 
 
 /**
@@ -75,15 +126,14 @@ struct _GMimeHeaderList {
  * Returns: a new #GMimeHeader with the specified values.
  **/
 static GMimeHeader *
-g_mime_header_new (GMimeHeaderList *headers, const char *name, const char *value, const char *raw_value, 
gint64 offset)
+g_mime_header_new (const char *name, const char *value, const char *raw_value, gint64 offset)
 {
        GMimeHeader *header;
        
-       header = g_slice_new (GMimeHeader);
-       header->list = headers;
-       header->name = g_strdup (name);
-       header->value = g_strdup (value);
+       header = g_object_newv (GMIME_TYPE_HEADER, 0, NULL);
        header->raw_value = raw_value ? g_strdup (raw_value) : NULL;
+       header->value = g_strdup (value);
+       header->name = g_strdup (name);
        header->offset = offset;
        
        return header;
@@ -91,23 +141,6 @@ g_mime_header_new (GMimeHeaderList *headers, const char *name, const char *value
 
 
 /**
- * g_mime_header_free:
- * @header: a #GMimeHeader
- *
- * Frees a single #GMimeHeader node.
- **/
-static void
-g_mime_header_free (GMimeHeader *header)
-{
-       g_free (header->name);
-       g_free (header->value);
-       g_free (header->raw_value);
-       
-       g_slice_free (GMimeHeader, header);
-}
-
-
-/**
  * g_mime_header_get_name:
  * @header: a #GMimeHeader
  *
@@ -118,7 +151,7 @@ g_mime_header_free (GMimeHeader *header)
 const char *
 g_mime_header_get_name (GMimeHeader *header)
 {
-       g_return_val_if_fail (header != NULL, NULL);
+       g_return_val_if_fail (GMIME_IS_HEADER (header), NULL);
        
        return header->name;
 }
@@ -138,7 +171,7 @@ g_mime_header_get_name (GMimeHeader *header)
 const char *
 g_mime_header_get_value (GMimeHeader *header)
 {
-       g_return_val_if_fail (header != NULL, NULL);
+       g_return_val_if_fail (GMIME_IS_HEADER (header), NULL);
        
        return header->value;
 }
@@ -157,9 +190,7 @@ g_mime_header_get_value (GMimeHeader *header)
 void
 g_mime_header_set_value (GMimeHeader *header, const char *value)
 {
-       GMimeHeaderListChangedEventArgs args;
-       
-       g_return_if_fail (header != NULL);
+       g_return_if_fail (GMIME_IS_HEADER (header));
        g_return_if_fail (value != NULL);
        
        g_free (header->raw_value);
@@ -167,10 +198,7 @@ g_mime_header_set_value (GMimeHeader *header, const char *value)
        
        header->value = g_strdup (value);
        
-       args.action = GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED;
-       args.header = header;
-       
-       g_mime_event_emit (header->list->changed, &args);
+       g_mime_event_emit (header->changed, NULL);
 }
 
 
@@ -185,7 +213,7 @@ g_mime_header_set_value (GMimeHeader *header, const char *value)
 const char *
 _g_mime_header_get_raw_value (GMimeHeader *header)
 {
-       g_return_val_if_fail (header != NULL, NULL);
+       g_return_val_if_fail (GMIME_IS_HEADER (header), NULL);
        
        return header->raw_value;
 }
@@ -201,7 +229,7 @@ _g_mime_header_get_raw_value (GMimeHeader *header)
 void
 _g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
 {
-       g_return_if_fail (header != NULL);
+       g_return_if_fail (GMIME_IS_HEADER (header));
        g_return_if_fail (raw_value != NULL);
        
        g_free (header->raw_value);
@@ -221,7 +249,7 @@ _g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
 gint64
 g_mime_header_get_offset (GMimeHeader *header)
 {
-       g_return_val_if_fail (header != NULL, -1);
+       g_return_val_if_fail (GMIME_IS_HEADER (header), -1);
        
        return header->offset;
 }
@@ -257,13 +285,14 @@ default_writer (GMimeParserOptions *options, GMimeStream *stream, const char *na
  * Returns: the number of bytes written, or %-1 on fail.
  **/
 ssize_t
-g_mime_header_write_to_stream (GMimeHeader *header, GMimeStream *stream)
+g_mime_header_write_to_stream (GMimeHeaderList *headers, GMimeHeader *header, GMimeStream *stream)
 {
        ssize_t nwritten, total = 0;
        GMimeHeaderWriter writer;
        char *val;
        
-       g_return_val_if_fail (header != NULL, -1);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), -1);
+       g_return_val_if_fail (GMIME_IS_HEADER (header), -1);
        g_return_val_if_fail (GMIME_IS_STREAM (stream), -1);
        
        if (header->raw_value) {
@@ -276,10 +305,10 @@ g_mime_header_write_to_stream (GMimeHeader *header, GMimeStream *stream)
                
                total += nwritten;
        } else if (header->value) {
-               if (!(writer = g_hash_table_lookup (header->list->writers, header->name)))
+               if (!(writer = g_hash_table_lookup (headers->writers, header->name)))
                        writer = default_writer;
                
-               if ((nwritten = writer (header->list->options, stream, header->name, header->value)) == -1)
+               if ((nwritten = writer (headers->options, stream, header->name, header->value)) == -1)
                        return -1;
                
                total += nwritten;
@@ -289,6 +318,93 @@ g_mime_header_write_to_stream (GMimeHeader *header, GMimeStream *stream)
 }
 
 
+static void g_mime_header_list_class_init (GMimeHeaderListClass *klass);
+static void g_mime_header_list_init (GMimeHeaderList *list, GMimeHeaderListClass *klass);
+static void g_mime_header_list_finalize (GObject *object);
+
+
+static GObjectClass *list_parent_class = NULL;
+
+
+GType
+g_mime_header_list_get_type (void)
+{
+       static GType type = 0;
+       
+       if (!type) {
+               static const GTypeInfo info = {
+                       sizeof (GMimeHeaderListClass),
+                       NULL, /* base_class_init */
+                       NULL, /* base_class_finalize */
+                       (GClassInitFunc) g_mime_header_list_class_init,
+                       NULL, /* class_finalize */
+                       NULL, /* class_data */
+                       sizeof (GMimeHeaderList),
+                       0,    /* n_preallocs */
+                       (GInstanceInitFunc) g_mime_header_list_init,
+               };
+               
+               type = g_type_register_static (G_TYPE_OBJECT, "GMimeHeaderList", &info, 0);
+       }
+       
+       return type;
+}
+
+
+static void
+g_mime_header_list_class_init (GMimeHeaderListClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       
+       list_parent_class = g_type_class_ref (G_TYPE_OBJECT);
+       
+       object_class->finalize = g_mime_header_list_finalize;
+}
+
+static void
+g_mime_header_list_init (GMimeHeaderList *list, GMimeHeaderListClass *klass)
+{
+       list->writers = g_hash_table_new_full (g_mime_strcase_hash,
+                                              g_mime_strcase_equal,
+                                              g_free, NULL);
+       list->hash = g_hash_table_new (g_mime_strcase_hash,
+                                      g_mime_strcase_equal);
+       list->changed = g_mime_event_new (list);
+       list->array = g_ptr_array_new ();
+}
+
+static void
+g_mime_header_list_finalize (GObject *object)
+{
+       GMimeHeaderList *headers = (GMimeHeaderList *) object;
+       guint i;
+       
+       for (i = 0; i < headers->array->len; i++)
+               g_object_unref (headers->array->pdata[i]);
+       
+       g_ptr_array_free (headers->array, TRUE);
+       
+       g_mime_parser_options_free (headers->options);
+       g_hash_table_destroy (headers->writers);
+       g_hash_table_destroy (headers->hash);
+       g_mime_event_free (headers->changed);
+       
+       G_OBJECT_CLASS (list_parent_class)->finalize (object);
+}
+
+
+static void
+header_changed (GMimeHeader *header, gpointer user_args, GMimeHeaderList *list)
+{
+       GMimeHeaderListChangedEventArgs args;
+       
+       args.action = GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED;
+       args.header = header;
+       
+       g_mime_event_emit (list->changed, &args);
+}
+
+
 /**
  * g_mime_header_list_new:
  * @options: a #GMimeParserOptions
@@ -304,49 +420,14 @@ g_mime_header_list_new (GMimeParserOptions *options)
        
        g_return_val_if_fail (options != NULL, NULL);
        
-       headers = g_slice_new (GMimeHeaderList);
+       headers = g_object_newv (GMIME_TYPE_HEADER_LIST, 0, NULL);
        headers->options = _g_mime_parser_options_clone (options);
-       headers->writers = g_hash_table_new_full (g_mime_strcase_hash,
-                                                 g_mime_strcase_equal,
-                                                 g_free, NULL);
-       headers->hash = g_hash_table_new (g_mime_strcase_hash,
-                                         g_mime_strcase_equal);
-       headers->changed = g_mime_event_new (headers);
-       headers->list = g_ptr_array_new ();
        
        return headers;
 }
 
 
 /**
- * g_mime_header_list_free:
- * @headers: a #GMimeHeaderList
- *
- * Frees the header list.
- **/
-void
-g_mime_header_list_free (GMimeHeaderList *headers)
-{
-       guint i;
-       
-       if (!headers)
-               return;
-       
-       for (i = 0; i < headers->list->len; i++)
-               g_mime_header_free (headers->list->pdata[i]);
-       
-       g_ptr_array_free (headers->list, TRUE);
-       
-       g_mime_parser_options_free (headers->options);
-       g_hash_table_destroy (headers->writers);
-       g_hash_table_destroy (headers->hash);
-       g_mime_event_free (headers->changed);
-       
-       g_slice_free (GMimeHeaderList, headers);
-}
-
-
-/**
  * g_mime_header_list_clear:
  * @headers: a #GMimeHeaderList
  *
@@ -356,16 +437,20 @@ void
 g_mime_header_list_clear (GMimeHeaderList *headers)
 {
        GMimeHeaderListChangedEventArgs args;
+       GMimeHeader *header;
        guint i;
        
-       g_return_if_fail (headers != NULL);
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
        
-       for (i = 0; i < headers->list->len; i++)
-               g_mime_header_free (headers->list->pdata[i]);
+       for (i = 0; i < headers->array->len; i++) {
+               header = (GMimeHeader *) headers->array->pdata[i];
+               g_mime_event_remove (header->changed, (GMimeEventCallback) header_changed, headers);
+               g_object_unref (header);
+       }
        
        g_hash_table_remove_all (headers->hash);
        
-       g_ptr_array_set_size (headers->list, 0);
+       g_ptr_array_set_size (headers->array, 0);
        
        args.action = GMIME_HEADER_LIST_CHANGED_ACTION_CLEARED;
        args.header = NULL;
@@ -399,9 +484,9 @@ _g_mime_header_list_set_options (GMimeHeaderList *headers, GMimeParserOptions *o
 int
 g_mime_header_list_get_count (GMimeHeaderList *headers)
 {
-       g_return_val_if_fail (headers != NULL, -1);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), -1);
        
-       return headers->list->len;
+       return headers->array->len;
 }
 
 
@@ -419,7 +504,7 @@ g_mime_header_list_contains (GMimeHeaderList *headers, const char *name)
 {
        GMimeHeader *header;
        
-       g_return_val_if_fail (headers != NULL, FALSE);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), FALSE);
        g_return_val_if_fail (name != NULL, FALSE);
        
        if (!(header = g_hash_table_lookup (headers->hash, name)))
@@ -449,20 +534,21 @@ _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const c
        GMimeHeader *header;
        guint n;
        
-       header = g_mime_header_new (headers, name, value, raw_value, offset);
+       header = g_mime_header_new (name, value, raw_value, offset);
+       g_mime_event_add (header->changed, (GMimeEventCallback) header_changed, headers);
        g_hash_table_replace (headers->hash, header->name, header);
        
-       if (headers->list->len > 0) {
-               g_ptr_array_set_size (headers->list, headers->list->len + 1);
+       if (headers->array->len > 0) {
+               g_ptr_array_set_size (headers->array, headers->array->len + 1);
                
-               dest = ((unsigned char *) headers->list->pdata) + sizeof (void *);
-               src = (unsigned char *) headers->list->pdata;
-               n = headers->list->len - 1;
+               dest = ((unsigned char *) headers->array->pdata) + sizeof (void *);
+               src = (unsigned char *) headers->array->pdata;
+               n = headers->array->len - 1;
                
                g_memmove (dest, src, (sizeof (void *) * n));
-               headers->list->pdata[0] = header;
+               headers->array->pdata[0] = header;
        } else {
-               g_ptr_array_add (headers->list, header);
+               g_ptr_array_add (headers->array, header);
        }
        
        args.action = GMIME_HEADER_LIST_CHANGED_ACTION_ADDED;
@@ -488,7 +574,7 @@ _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const c
 void
 g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value)
 {
-       g_return_if_fail (headers != NULL);
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
        g_return_if_fail (name != NULL);
        
        _g_mime_header_list_prepend (headers, name, value, NULL, -1);
@@ -501,8 +587,9 @@ _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const ch
        GMimeHeaderListChangedEventArgs args;
        GMimeHeader *header;
        
-       header = g_mime_header_new (headers, name, value, raw_value, offset);
-       g_ptr_array_add (headers->list, header);
+       header = g_mime_header_new (name, value, raw_value, offset);
+       g_mime_event_add (header->changed, (GMimeEventCallback) header_changed, headers);
+       g_ptr_array_add (headers->array, header);
        
        if (!g_hash_table_lookup (headers->hash, name))
                g_hash_table_insert (headers->hash, header->name, header);
@@ -530,7 +617,7 @@ _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const ch
 void
 g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value)
 {
-       g_return_if_fail (headers != NULL);
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
        g_return_if_fail (name != NULL);
        
        _g_mime_header_list_append (headers, name, value, NULL, -1);
@@ -551,7 +638,7 @@ g_mime_header_list_get_header (GMimeHeaderList *headers, const char *name)
 {
        GMimeHeader *header;
        
-       g_return_val_if_fail (headers != NULL, NULL);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), NULL);
        g_return_val_if_fail (name != NULL, NULL);
        
        return g_hash_table_lookup (headers->hash, name);
@@ -574,8 +661,8 @@ _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char
                
                header->offset = offset;
                
-               for (i = headers->list->len - 1; i > 0; i--) {
-                       hdr = (GMimeHeader *) headers->list->pdata[i];
+               for (i = headers->array->len - 1; i > 0; i--) {
+                       hdr = (GMimeHeader *) headers->array->pdata[i];
                        
                        if (hdr == header)
                                break;
@@ -583,8 +670,9 @@ _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char
                        if (g_ascii_strcasecmp (header->name, hdr->name) != 0)
                                continue;
                        
-                       g_ptr_array_remove_index (headers->list, i);
-                       g_mime_header_free (hdr);
+                       g_mime_event_remove (hdr->changed, (GMimeEventCallback) header_changed, headers);
+                       g_ptr_array_remove_index (headers->array, i);
+                       g_object_unref (hdr);
                }
                
                args.action = GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED;
@@ -618,7 +706,7 @@ _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char
 void
 g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value)
 {
-       g_return_if_fail (headers != NULL);
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
        g_return_if_fail (name != NULL);
        
        _g_mime_header_list_set (headers, name, value, NULL, -1);
@@ -637,13 +725,13 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
 GMimeHeader *
 g_mime_header_list_get_header_at (GMimeHeaderList *headers, int index)
 {
-       g_return_val_if_fail (headers != NULL, NULL);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), NULL);
        g_return_val_if_fail (index >= 0, NULL);
        
-       if ((guint) index >= headers->list->len)
+       if ((guint) index >= headers->array->len)
                return NULL;
        
-       return (GMimeHeader *) headers->list->pdata[index];
+       return (GMimeHeader *) headers->array->pdata[index];
 }
 
 
@@ -664,24 +752,25 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name)
        GMimeHeader *header, *hdr;
        guint i;
        
-       g_return_val_if_fail (headers != NULL, FALSE);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), FALSE);
        g_return_val_if_fail (name != NULL, FALSE);
        
        if (!(header = g_hash_table_lookup (headers->hash, name)))
                return FALSE;
        
        /* get the index of the header */
-       for (i = 0; i < headers->list->len; i++) {
-               if (headers->list->pdata[i] == header)
+       for (i = 0; i < headers->array->len; i++) {
+               if (headers->array->pdata[i] == header)
                        break;
        }
        
-       g_ptr_array_remove_index (headers->list, i);
+       g_mime_event_remove (header->changed, (GMimeEventCallback) header_changed, headers);
+       g_ptr_array_remove_index (headers->array, i);
        g_hash_table_remove (headers->hash, name);
        
        /* look for another header with the same name... */
-       while (i < headers->list->len) {
-               hdr = (GMimeHeader *) headers->list->pdata[i];
+       while (i < headers->array->len) {
+               hdr = (GMimeHeader *) headers->array->pdata[i];
                
                if (!g_ascii_strcasecmp (hdr->name, name)) {
                        /* enter this node into the lookup table */
@@ -696,7 +785,7 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name)
        args.header = header;
        
        g_mime_event_emit (headers->changed, &args);
-       g_mime_header_free (header);
+       g_object_unref (header);
        
        return TRUE;
 }
@@ -716,22 +805,23 @@ g_mime_header_list_remove_at (GMimeHeaderList *headers, int index)
        GMimeHeader *header, *hdr;
        guint i;
        
-       g_return_if_fail (headers != NULL);
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
        g_return_if_fail (index >= 0);
        
-       if ((guint) index >= headers->list->len)
+       if ((guint) index >= headers->array->len)
                return;
        
-       header = (GMimeHeader *) headers->list->pdata[index];
-       g_ptr_array_remove_index (headers->list, index);
+       header = (GMimeHeader *) headers->array->pdata[index];
+       g_mime_event_remove (header->changed, (GMimeEventCallback) header_changed, headers);
+       g_ptr_array_remove_index (headers->array, index);
        
        /* if this is the first instance of a header with this name, then we'll
         * need to update the hash table to point to the next instance... */
        if ((hdr = g_hash_table_lookup (headers->hash, header->name)) == header) {
                g_hash_table_remove (headers->hash, header->name);
                
-               for (i = (guint) index; i < headers->list->len; i++) {
-                       hdr = (GMimeHeader *) headers->list->pdata[i];
+               for (i = (guint) index; i < headers->array->len; i++) {
+                       hdr = (GMimeHeader *) headers->array->pdata[i];
                        
                        if (!g_ascii_strcasecmp (header->name, hdr->name)) {
                                g_hash_table_insert (headers->hash, hdr->name, hdr);
@@ -744,7 +834,7 @@ g_mime_header_list_remove_at (GMimeHeaderList *headers, int index)
        args.header = header;
        
        g_mime_event_emit (headers->changed, &args);
-       g_mime_header_free (header);
+       g_object_unref (header);
 }
 
 
@@ -764,13 +854,13 @@ g_mime_header_list_write_to_stream (GMimeHeaderList *headers, GMimeStream *strea
        GMimeHeader *header;
        guint i;
        
-       g_return_val_if_fail (headers != NULL, -1);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), -1);
        g_return_val_if_fail (stream != NULL, -1);
        
-       for (i = 0; i < headers->list->len; i++) {
-               header = (GMimeHeader *) headers->list->pdata[i];
+       for (i = 0; i < headers->array->len; i++) {
+               header = (GMimeHeader *) headers->array->pdata[i];
                
-               if ((nwritten = g_mime_header_write_to_stream (header, stream)) == -1)
+               if ((nwritten = g_mime_header_write_to_stream (headers, header, stream)) == -1)
                        return -1;
                
                total += nwritten;
@@ -796,7 +886,7 @@ g_mime_header_list_to_string (GMimeHeaderList *headers)
        GByteArray *array;
        char *str;
        
-       g_return_val_if_fail (headers != NULL, NULL);
+       g_return_val_if_fail (GMIME_IS_HEADER_LIST (headers), NULL);
        
        array = g_byte_array_new ();
        stream = g_mime_stream_mem_new ();
@@ -827,7 +917,7 @@ g_mime_header_list_register_writer (GMimeHeaderList *headers, const char *name,
 {
        gpointer okey, oval;
        
-       g_return_if_fail (headers != NULL);
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
        g_return_if_fail (name != NULL);
        
        g_hash_table_remove (headers->writers, name);
@@ -835,12 +925,3 @@ g_mime_header_list_register_writer (GMimeHeaderList *headers, const char *name,
        if (writer)
                g_hash_table_insert (headers->writers, g_strdup (name), writer);
 }
-
-
-GMimeEvent *
-_g_mime_header_list_get_changed_event (GMimeHeaderList *headers)
-{
-       g_return_val_if_fail (headers != NULL, NULL);
-       
-       return headers->changed;
-}
diff --git a/gmime/gmime-header.h b/gmime/gmime-header.h
index 2827a13..7a9ffe2 100644
--- a/gmime/gmime-header.h
+++ b/gmime/gmime-header.h
@@ -28,6 +28,26 @@
 
 G_BEGIN_DECLS
 
+#define GMIME_TYPE_HEADER                  (g_mime_header_get_type ())
+#define GMIME_HEADER(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_HEADER, 
GMimeHeader))
+#define GMIME_HEADER_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_HEADER, 
GMimeHeaderClass))
+#define GMIME_IS_HEADER(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_HEADER))
+#define GMIME_IS_HEADER_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_HEADER))
+#define GMIME_HEADER_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_HEADER, 
GMimeHeaderClass))
+
+#define GMIME_TYPE_HEADER_LIST             (g_mime_header_list_get_type ())
+#define GMIME_HEADER_LIST(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_HEADER_LIST, 
GMimeHeaderList))
+#define GMIME_HEADER_LIST_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_HEADER_LIST, 
GMimeHeaderListClass))
+#define GMIME_IS_HEADER_LIST(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_HEADER_LIST))
+#define GMIME_IS_HEADER_LIST_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_HEADER_LIST))
+#define GMIME_HEADER_LIST_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_HEADER_LIST, 
GMimeHeaderListClass))
+
+typedef struct _GMimeHeader GMimeHeader;
+typedef struct _GMimeHeaderClass GMimeHeaderClass;
+
+typedef struct _GMimeHeaderList GMimeHeaderList;
+typedef struct _GMimeHeaderListClass GMimeHeaderListClass;
+
 
 /**
  * GMimeHeaderWriter:
@@ -46,10 +66,30 @@ typedef ssize_t (* GMimeHeaderWriter) (GMimeParserOptions *options, GMimeStream
 
 /**
  * GMimeHeader:
+ * @name: the name of the header
+ * @value: the unfolded value of the header
  *
- * A message/rfc822 header.
+ * A message or mime-part header.
  **/
-typedef struct _GMimeHeader GMimeHeader;
+struct _GMimeHeader {
+       GObject parent_object;
+       
+       char *name, *value;
+       
+       /* < private > */
+       gpointer changed;
+       char *raw_value;
+       char *raw_name;
+       gint64 offset;
+};
+
+struct _GMimeHeaderClass {
+       GObjectClass parent_class;
+       
+};
+
+
+GType g_mime_header_get_type (void);
 
 const char *g_mime_header_get_name (GMimeHeader *header);
 
@@ -58,7 +98,7 @@ void g_mime_header_set_value (GMimeHeader *header, const char *value);
 
 gint64 g_mime_header_get_offset (GMimeHeader *header);
 
-ssize_t g_mime_header_write_to_stream (GMimeHeader *header, GMimeStream *stream);
+ssize_t g_mime_header_write_to_stream (GMimeHeaderList *headers, GMimeHeader *header, GMimeStream *stream);
 
 
 /**
@@ -66,10 +106,26 @@ ssize_t g_mime_header_write_to_stream (GMimeHeader *header, GMimeStream *stream)
  *
  * A list of message or mime-part headers.
  **/
-typedef struct _GMimeHeaderList GMimeHeaderList;
+struct _GMimeHeaderList {
+       GObject parent_object;
+       
+       /* < private > */
+       GMimeParserOptions *options;
+       GHashTable *writers;
+       gpointer changed;
+       GHashTable *hash;
+       GPtrArray *array;
+};
+
+struct _GMimeHeaderListClass {
+       GObjectClass parent_class;
+       
+};
+
+
+GType g_mime_header_list_get_type (void);
 
 GMimeHeaderList *g_mime_header_list_new (GMimeParserOptions *options);
-void g_mime_header_list_free (GMimeHeaderList *headers);
 
 void g_mime_header_list_clear (GMimeHeaderList *headers);
 int g_mime_header_list_get_count (GMimeHeaderList *headers);
diff --git a/gmime/gmime-internal.h b/gmime/gmime-internal.h
index 9fe0ef5..79b9b80 100644
--- a/gmime/gmime-internal.h
+++ b/gmime/gmime-internal.h
@@ -58,7 +58,6 @@ G_GNUC_INTERNAL gboolean _g_mime_header_list_has_raw_value (GMimeHeaderList *hea
 G_GNUC_INTERNAL void _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char 
*value, const char *raw_value, gint64 offset);
 G_GNUC_INTERNAL void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char 
*value, const char *raw_value, gint64 offset);
 G_GNUC_INTERNAL void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value, 
const char *raw_value, gint64 offset);
-G_GNUC_INTERNAL GMimeEvent *_g_mime_header_list_get_changed_event (GMimeHeaderList *headers);
 
 /* GMimeObject */
 G_GNUC_INTERNAL void _g_mime_object_block_header_list_changed (GMimeObject *object);
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 3eaeaaa..b5330ea 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -869,13 +869,13 @@ write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
                        offset = g_mime_header_get_offset (header);
                        
                        if (offset >= 0 && offset < body_offset) {
-                               if ((nwritten = g_mime_header_write_to_stream (header, stream)) == -1)
+                               if ((nwritten = g_mime_header_write_to_stream (object->headers, header, 
stream)) == -1)
                                        return -1;
                                
                                total += nwritten;
                                index++;
                        } else {
-                               if ((nwritten = g_mime_header_write_to_stream (body_header, stream)) == -1)
+                               if ((nwritten = g_mime_header_write_to_stream (mime_part->headers, 
body_header, stream)) == -1)
                                        return -1;
                                
                                total += nwritten;
@@ -886,7 +886,7 @@ write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
                while (index < count) {
                        header = g_mime_header_list_get_header_at (object->headers, index);
                        
-                       if ((nwritten = g_mime_header_write_to_stream (header, stream)) == -1)
+                       if ((nwritten = g_mime_header_write_to_stream (object->headers, header, stream)) == 
-1)
                                return -1;
                        
                        total += nwritten;
@@ -896,7 +896,7 @@ write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
                while (body_index < body_count) {
                        header = g_mime_header_list_get_header_at (mime_part->headers, body_index);
                        
-                       if ((nwritten = g_mime_header_write_to_stream (header, stream)) == -1)
+                       if ((nwritten = g_mime_header_write_to_stream (mime_part->headers, header, stream)) 
== -1)
                                return -1;
                        
                        total += nwritten;
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index 168c7b4..a17e662 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -134,11 +134,11 @@ g_mime_object_class_init (GMimeObjectClass *klass)
 static void
 g_mime_object_init (GMimeObject *object, GMimeObjectClass *klass)
 {
-       GMimeEvent *changed;
+       GMimeHeaderList *headers;
        
-       object->headers = g_mime_header_list_new (g_mime_parser_options_get_default ());
-       changed = _g_mime_header_list_get_changed_event (object->headers);
-       g_mime_event_add (changed, (GMimeEventCallback) header_list_changed, object);
+       headers = g_mime_header_list_new (g_mime_parser_options_get_default ());
+       g_mime_event_add (headers->changed, (GMimeEventCallback) header_list_changed, object);
+       object->headers = headers;
        
        object->content_type = NULL;
        object->disposition = NULL;
@@ -168,9 +168,9 @@ g_mime_object_finalize (GObject *object)
        }
        
        if (mime->headers) {
-               event = _g_mime_header_list_get_changed_event (mime->headers);
+               event = mime->headers->changed;
                g_mime_event_remove (event, (GMimeEventCallback) header_list_changed, object);
-               g_mime_header_list_free (mime->headers);
+               g_object_unref (mime->headers);
        }
        
        g_free (mime->content_id);
@@ -333,19 +333,13 @@ write_content_type (GMimeParserOptions *options, GMimeStream *stream, const char
 void
 _g_mime_object_block_header_list_changed (GMimeObject *object)
 {
-       GMimeEvent *event;
-       
-       event = _g_mime_header_list_get_changed_event (object->headers);
-       g_mime_event_block (event, (GMimeEventCallback) header_list_changed, object);
+       g_mime_event_block (object->headers->changed, (GMimeEventCallback) header_list_changed, object);
 }
 
 void
 _g_mime_object_unblock_header_list_changed (GMimeObject *object)
 {
-       GMimeEvent *event;
-       
-       event = _g_mime_header_list_get_changed_event (object->headers);
-       g_mime_event_unblock (event, (GMimeEventCallback) header_list_changed, object);
+       g_mime_event_unblock (object->headers->changed, (GMimeEventCallback) header_list_changed, object);
 }
 
 static char *
diff --git a/tests/test-headers.c b/tests/test-headers.c
index aa1ce45..affd2cd 100644
--- a/tests/test-headers.c
+++ b/tests/test-headers.c
@@ -106,7 +106,7 @@ test_indexing (void)
                testsuite_check_failed ("indexing past end of headers: %s", ex->message);
        } finally;
        
-       g_mime_header_list_free (list);
+       g_object_unref (list);
 }
 
 static void
@@ -162,7 +162,7 @@ test_remove (void)
                testsuite_check_failed ("remove last header: %s", ex->message);
        } finally;
        
-       g_mime_header_list_free (list);
+       g_object_unref (list);
 }
 
 static void
@@ -219,7 +219,7 @@ test_remove_at (void)
                testsuite_check_failed ("remove last header: %s", ex->message);
        } finally;
        
-       g_mime_header_list_free (list);
+       g_object_unref (list);
 }
 
 static void


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