Rename private notmuch_message_t to notmuch_message_file_t
authorCarl Worth <cworth@cworth.org>
Tue, 20 Oct 2009 22:09:51 +0000 (15:09 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 20 Oct 2009 22:09:51 +0000 (15:09 -0700)
This is in preparation for a new, public notmuch_message_t.

Eventually, the public notmuch_message_t is going to grow enough
features to need to be file-backed and will likely need everything
that's now in message-file.c. So we may fold these back into one
object/implementation in the future.

Makefile
database.cc
message-file.c [new file with mode: 0644]
message.c [deleted file]
notmuch-private.h

index 86516402c2eda51d4d628f3cbb61a93240afde85..34716c294bb6233ab6ec2e17ca377a65da2c177a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ all: $(PROGS)
 %.o: %.c
        $(CC) -c $(CFLAGS) $(MYCFLAGS) $< -o $@
 
-notmuch: notmuch.o database.o date.o message.o xutil.o
+notmuch: notmuch.o database.o date.o message-file.o xutil.o
        $(CC) $(MYLDFLAGS) $^ -o $@
 
 Makefile.dep: *.c *.cc
index 59e837360018a72aeff4195f21b0b3b724e75334..7e678d87b8a506524663814e55b502309c74ed37 100644 (file)
@@ -501,7 +501,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
 {
     Xapian::WritableDatabase *db = notmuch->xapian_db;
     Xapian::Document doc;
-    notmuch_message_t *message;
+    notmuch_message_file_t *message;
 
     GPtrArray *parents, *thread_ids;
 
@@ -512,16 +512,16 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
     time_t time_value;
     unsigned int i;
 
-    message = notmuch_message_open (filename);
+    message = notmuch_message_file_open (filename);
 
-    notmuch_message_restrict_headers (message,
-                                     "date",
-                                     "from",
-                                     "in-reply-to",
-                                     "message-id",
-                                     "references",
-                                     "subject",
-                                     (char *) NULL);
+    notmuch_message_file_restrict_headers (message,
+                                          "date",
+                                          "from",
+                                          "in-reply-to",
+                                          "message-id",
+                                          "references",
+                                          "subject",
+                                          (char *) NULL);
 
     try {
        doc = Xapian::Document ();
@@ -530,16 +530,16 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
 
        parents = g_ptr_array_new ();
 
-       refs = notmuch_message_get_header (message, "references");
+       refs = notmuch_message_file_get_header (message, "references");
        parse_references (parents, refs);
 
-       in_reply_to = notmuch_message_get_header (message, "in-reply-to");
+       in_reply_to = notmuch_message_file_get_header (message, "in-reply-to");
        parse_references (parents, in_reply_to);
 
        for (i = 0; i < parents->len; i++)
            add_term (doc, "ref", (char *) g_ptr_array_index (parents, i));
 
-       header = notmuch_message_get_header (message, "message-id");
+       header = notmuch_message_file_get_header (message, "message-id");
        if (header) {
            message_id = parse_message_id (header, NULL);
            /* So the header value isn't RFC-compliant, but it's
@@ -592,21 +592,21 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
 
        free (message_id);
 
-       date = notmuch_message_get_header (message, "date");
+       date = notmuch_message_file_get_header (message, "date");
        time_value = notmuch_parse_date (date, NULL);
 
        doc.add_value (NOTMUCH_VALUE_DATE,
                       Xapian::sortable_serialise (time_value));
 
-       from = notmuch_message_get_header (message, "from");
-       subject = notmuch_message_get_header (message, "subject");
-       to = notmuch_message_get_header (message, "to");
+       from = notmuch_message_file_get_header (message, "from");
+       subject = notmuch_message_file_get_header (message, "subject");
+       to = notmuch_message_file_get_header (message, "to");
 
        if (from == NULL &&
            subject == NULL &&
            to == NULL)
        {
-           notmuch_message_close (message);
+           notmuch_message_file_close (message);
            return NOTMUCH_STATUS_FILE_NOT_EMAIL;
        } else {
            db->add_document (doc);
@@ -617,7 +617,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
        return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
 
-    notmuch_message_close (message);
+    notmuch_message_file_close (message);
 
     return NOTMUCH_STATUS_SUCCESS;
 }
diff --git a/message-file.c b/message-file.c
new file mode 100644 (file)
index 0000000..4f4f551
--- /dev/null
@@ -0,0 +1,302 @@
+/* message.c - Utility functions for parsing an email message for notmuch.
+ *
+ * Copyright © 2009 Carl Worth
+ *
+ * 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 3 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, see http://www.gnu.org/licenses/ .
+ *
+ * Author: Carl Worth <cworth@cworth.org>
+ */
+
+#include <stdarg.h>
+
+#include "notmuch-private.h"
+
+#include <glib.h> /* GHashTable */
+
+typedef struct {
+    char *str;
+    size_t size;
+    size_t len;
+} header_value_closure_t;
+
+struct _notmuch_message_file {
+    /* File object */
+    FILE *file;
+
+    /* Header storage */
+    int restrict_headers;
+    GHashTable *headers;
+    int broken_headers;
+    int good_headers;
+
+    /* Parsing state */
+    char *line;
+    size_t line_size;
+    header_value_closure_t value;
+
+    int parsing_started;
+    int parsing_finished;
+};
+
+static int
+strcase_equal (const void *a, const void *b)
+{
+    return strcasecmp (a, b) == 0;
+}
+
+static unsigned int
+strcase_hash (const void *ptr)
+{
+    const char *s = ptr;
+
+    /* This is the djb2 hash. */
+    unsigned int hash = 5381;
+    while (s && *s) {
+       hash = ((hash << 5) + hash) + tolower (*s);
+       s++;
+    }
+
+    return hash;
+}
+
+notmuch_message_file_t *
+notmuch_message_file_open (const char *filename)
+{
+    notmuch_message_file_t *message;
+
+    message = xcalloc (1, sizeof (notmuch_message_file_t));
+
+    message->file = fopen (filename, "r");
+    if (message->file == NULL)
+       goto FAIL;
+
+    message->headers = g_hash_table_new_full (strcase_hash,
+                                             strcase_equal,
+                                             free,
+                                             free);
+
+    message->parsing_started = 0;
+    message->parsing_finished = 0;
+
+    return message;
+
+  FAIL:
+    fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
+    notmuch_message_file_close (message);
+
+    return NULL;
+}
+
+void
+notmuch_message_file_close (notmuch_message_file_t *message)
+{
+    if (message == NULL)
+       return;
+
+    if (message->line)
+       free (message->line);
+
+    if (message->value.size)
+       free (message->value.str);
+
+    if (message->headers)
+       g_hash_table_destroy (message->headers);
+
+    if (message->file)
+       fclose (message->file);
+
+    free (message);
+}
+
+void
+notmuch_message_file_restrict_headersv (notmuch_message_file_t *message,
+                                       va_list va_headers)
+{
+    char *header;
+
+    if (message->parsing_started ) {
+       fprintf (stderr, "Error: notmuch_message_file_restrict_headers called after parsing has started\n");
+       exit (1);
+    }
+
+    while (1) {
+       header = va_arg (va_headers, char*);
+       if (header == NULL)
+           break;
+       g_hash_table_insert (message->headers,
+                            xstrdup (header), NULL);
+    }
+
+    message->restrict_headers = 1;
+}
+
+void
+notmuch_message_file_restrict_headers (notmuch_message_file_t *message, ...)
+{
+    va_list va_headers;
+
+    va_start (va_headers, message);
+
+    notmuch_message_file_restrict_headersv (message, va_headers);
+}
+
+void
+copy_header_unfolding (header_value_closure_t *value,
+                      const char *chunk)
+{
+    char *last;
+
+    if (chunk == NULL)
+       return;
+
+    while (*chunk == ' ' || *chunk == '\t')
+       chunk++;
+
+    if (value->len + 1 + strlen (chunk) + 1 > value->size) {
+       int new_size = value->size;
+       if (value->size == 0)
+           new_size = strlen (chunk) + 1;
+       else
+           while (value->len + 1 + strlen (chunk) + 1 > new_size)
+               new_size *= 2;
+       value->str = xrealloc (value->str, new_size);
+       value->size = new_size;
+    }
+
+    last = value->str + value->len;
+    if (value->len) {
+       *last = ' ';
+       last++;
+       value->len++;
+    }
+
+    strcpy (last, chunk);
+    value->len += strlen (chunk);
+
+    last = value->str + value->len - 1;
+    if (*last == '\n') {
+       *last = '\0';
+       value->len--;
+    }
+}
+
+const char *
+notmuch_message_file_get_header (notmuch_message_file_t *message,
+                                const char *header_desired)
+{
+    int contains;
+    char *header, *value;
+    const char *s, *colon;
+    int match;
+
+    message->parsing_started = 1;
+
+    contains = g_hash_table_lookup_extended (message->headers,
+                                            header_desired, NULL,
+                                            (gpointer *) &value);
+    if (contains && value)
+       return value;
+
+    if (message->parsing_finished)
+       return NULL;
+
+#define NEXT_HEADER_LINE(closure)                              \
+    do {                                                       \
+       ssize_t bytes_read = getline (&message->line,           \
+                                     &message->line_size,      \
+                                     message->file);           \
+       if (bytes_read == -1) {                                 \
+           message->parsing_finished = 1;                      \
+           break;                                              \
+       }                                                       \
+       if (*message->line == '\n') {                           \
+           message->parsing_finished = 1;                      \
+           break;                                              \
+       }                                                       \
+       if (closure &&                                          \
+           (*message->line == ' ' || *message->line == '\t'))  \
+       {                                                       \
+           copy_header_unfolding ((closure), message->line);   \
+       }                                                       \
+    } while (*message->line == ' ' || *message->line == '\t');
+
+    if (message->line == NULL)
+       NEXT_HEADER_LINE (NULL);
+
+    while (1) {
+
+       if (message->parsing_finished)
+           break;
+
+       colon = strchr (message->line, ':');
+
+       if (colon == NULL) {
+           message->broken_headers++;
+           /* A simple heuristic for giving up on things that just
+            * don't look like mail messages. */
+           if (message->broken_headers >= 10 &&
+               message->good_headers < 5)
+           {
+               message->parsing_finished = 1;
+               continue;
+           }
+           NEXT_HEADER_LINE (NULL);
+           continue;
+       }
+
+       message->good_headers++;
+
+       header = xstrndup (message->line, colon - message->line);
+
+       if (message->restrict_headers &&
+           ! g_hash_table_lookup_extended (message->headers,
+                                           header, NULL, NULL))
+       {
+           free (header);
+           NEXT_HEADER_LINE (NULL);
+           continue;
+       }
+
+       s = colon + 1;
+       while (*s == ' ' || *s == '\t')
+           s++;
+
+       message->value.len = 0;
+       copy_header_unfolding (&message->value, s);
+
+       NEXT_HEADER_LINE (&message->value);
+
+       match = (strcasecmp (header, header_desired) == 0);
+
+       value = xstrdup (message->value.str);
+
+       g_hash_table_insert (message->headers, header, value);
+
+       if (match)
+           return value;
+    }
+
+    if (message->line)
+       free (message->line);
+    message->line = NULL;
+
+    if (message->value.size) {
+       free (message->value.str);
+       message->value.str = NULL;
+       message->value.size = 0;
+       message->value.len = 0;
+    }
+
+    return NULL;
+}
diff --git a/message.c b/message.c
deleted file mode 100644 (file)
index d888b24..0000000
--- a/message.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* message.c - Utility functions for parsing an email message for notmuch.
- *
- * Copyright © 2009 Carl Worth
- *
- * 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 3 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, see http://www.gnu.org/licenses/ .
- *
- * Author: Carl Worth <cworth@cworth.org>
- */
-
-#include <stdarg.h>
-
-#include "notmuch-private.h"
-
-#include <glib.h> /* GHashTable */
-
-typedef struct {
-    char *str;
-    size_t size;
-    size_t len;
-} header_value_closure_t;
-
-struct _notmuch_message {
-    /* File object */
-    FILE *file;
-
-    /* Header storage */
-    int restrict_headers;
-    GHashTable *headers;
-    int broken_headers;
-    int good_headers;
-
-    /* Parsing state */
-    char *line;
-    size_t line_size;
-    header_value_closure_t value;
-
-    int parsing_started;
-    int parsing_finished;
-};
-
-static int
-strcase_equal (const void *a, const void *b)
-{
-    return strcasecmp (a, b) == 0;
-}
-
-static unsigned int
-strcase_hash (const void *ptr)
-{
-    const char *s = ptr;
-
-    /* This is the djb2 hash. */
-    unsigned int hash = 5381;
-    while (s && *s) {
-       hash = ((hash << 5) + hash) + tolower (*s);
-       s++;
-    }
-
-    return hash;
-}
-
-notmuch_message_t *
-notmuch_message_open (const char *filename)
-{
-    notmuch_message_t *message;
-
-    message = xcalloc (1, sizeof (notmuch_message_t));
-
-    message->file = fopen (filename, "r");
-    if (message->file == NULL)
-       goto FAIL;
-
-    message->headers = g_hash_table_new_full (strcase_hash,
-                                             strcase_equal,
-                                             free,
-                                             free);
-
-    message->parsing_started = 0;
-    message->parsing_finished = 0;
-
-    return message;
-
-  FAIL:
-    fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
-    notmuch_message_close (message);
-
-    return NULL;
-}
-
-void
-notmuch_message_close (notmuch_message_t *message)
-{
-    if (message == NULL)
-       return;
-
-    if (message->line)
-       free (message->line);
-
-    if (message->value.size)
-       free (message->value.str);
-
-    if (message->headers)
-       g_hash_table_destroy (message->headers);
-
-    if (message->file)
-       fclose (message->file);
-
-    free (message);
-}
-
-void
-notmuch_message_restrict_headersv (notmuch_message_t *message,
-                                  va_list va_headers)
-{
-    char *header;
-
-    if (message->parsing_started ) {
-       fprintf (stderr, "Error: notmuch_message_restrict_headers called after parsing has started\n");
-       exit (1);
-    }
-
-    while (1) {
-       header = va_arg (va_headers, char*);
-       if (header == NULL)
-           break;
-       g_hash_table_insert (message->headers,
-                            xstrdup (header), NULL);
-    }
-
-    message->restrict_headers = 1;
-}
-
-void
-notmuch_message_restrict_headers (notmuch_message_t *message, ...)
-{
-    va_list va_headers;
-
-    va_start (va_headers, message);
-
-    notmuch_message_restrict_headersv (message, va_headers);
-}
-
-void
-copy_header_unfolding (header_value_closure_t *value,
-                      const char *chunk)
-{
-    char *last;
-
-    if (chunk == NULL)
-       return;
-
-    while (*chunk == ' ' || *chunk == '\t')
-       chunk++;
-
-    if (value->len + 1 + strlen (chunk) + 1 > value->size) {
-       int new_size = value->size;
-       if (value->size == 0)
-           new_size = strlen (chunk) + 1;
-       else
-           while (value->len + 1 + strlen (chunk) + 1 > new_size)
-               new_size *= 2;
-       value->str = xrealloc (value->str, new_size);
-       value->size = new_size;
-    }
-
-    last = value->str + value->len;
-    if (value->len) {
-       *last = ' ';
-       last++;
-       value->len++;
-    }
-
-    strcpy (last, chunk);
-    value->len += strlen (chunk);
-
-    last = value->str + value->len - 1;
-    if (*last == '\n') {
-       *last = '\0';
-       value->len--;
-    }
-}
-
-const char *
-notmuch_message_get_header (notmuch_message_t *message,
-                           const char *header_desired)
-{
-    int contains;
-    char *header, *value;
-    const char *s, *colon;
-    int match;
-
-    message->parsing_started = 1;
-
-    contains = g_hash_table_lookup_extended (message->headers,
-                                            header_desired, NULL,
-                                            (gpointer *) &value);
-    if (contains && value)
-       return value;
-
-    if (message->parsing_finished)
-       return NULL;
-
-#define NEXT_HEADER_LINE(closure)                              \
-    do {                                                       \
-       ssize_t bytes_read = getline (&message->line,           \
-                                     &message->line_size,      \
-                                     message->file);           \
-       if (bytes_read == -1) {                                 \
-           message->parsing_finished = 1;                      \
-           break;                                              \
-       }                                                       \
-       if (*message->line == '\n') {                           \
-           message->parsing_finished = 1;                      \
-           break;                                              \
-       }                                                       \
-       if (closure &&                                          \
-           (*message->line == ' ' || *message->line == '\t'))  \
-       {                                                       \
-           copy_header_unfolding ((closure), message->line);   \
-       }                                                       \
-    } while (*message->line == ' ' || *message->line == '\t');
-
-    if (message->line == NULL)
-       NEXT_HEADER_LINE (NULL);
-
-    while (1) {
-
-       if (message->parsing_finished)
-           break;
-
-       colon = strchr (message->line, ':');
-
-       if (colon == NULL) {
-           message->broken_headers++;
-           /* A simple heuristic for giving up on things that just
-            * don't look like mail messages. */
-           if (message->broken_headers >= 10 &&
-               message->good_headers < 5)
-           {
-               message->parsing_finished = 1;
-               continue;
-           }
-           NEXT_HEADER_LINE (NULL);
-           continue;
-       }
-
-       message->good_headers++;
-
-       header = xstrndup (message->line, colon - message->line);
-
-       if (message->restrict_headers &&
-           ! g_hash_table_lookup_extended (message->headers,
-                                           header, NULL, NULL))
-       {
-           free (header);
-           NEXT_HEADER_LINE (NULL);
-           continue;
-       }
-
-       s = colon + 1;
-       while (*s == ' ' || *s == '\t')
-           s++;
-
-       message->value.len = 0;
-       copy_header_unfolding (&message->value, s);
-
-       NEXT_HEADER_LINE (&message->value);
-
-       match = (strcasecmp (header, header_desired) == 0);
-
-       value = xstrdup (message->value.str);
-
-       g_hash_table_insert (message->headers, header, value);
-
-       if (match)
-           return value;
-    }
-
-    if (message->line)
-       free (message->line);
-    message->line = NULL;
-
-    if (message->value.size) {
-       free (message->value.str);
-       message->value.str = NULL;
-       message->value.size = 0;
-       message->value.len = 0;
-    }
-
-    return NULL;
-}
index a8ec8ebeee1371e9a5522669a1515be2394ae6d6..0c20a3c47320bc7275aaaabfe73156be2bdb2d5b 100644 (file)
@@ -57,13 +57,13 @@ xstrdup (const char *s);
 char *
 xstrndup (const char *s, size_t n);
 
-/* message.c */
+/* message-file.c */
 
 /* XXX: I haven't decided yet whether these will actually get exported
  * into the public interface in notmuch.h
  */
 
-typedef struct _notmuch_message notmuch_message_t;
+typedef struct _notmuch_message_file notmuch_message_file_t;
 
 /* Open a file containing a single email message.
  *
@@ -71,12 +71,12 @@ typedef struct _notmuch_message notmuch_message_t;
  *
  * Returns NULL if any error occurs.
  */
-notmuch_message_t *
-notmuch_message_open (const char *filename);
+notmuch_message_file_t *
+notmuch_message_file_open (const char *filename);
 
 /* Close a notmuch message preivously opened with notmuch_message_open. */
 void
-notmuch_message_close (notmuch_message_t *message);
+notmuch_message_file_close (notmuch_message_file_t *message);
 
 /* Restrict 'message' to only save the named headers.
  *
@@ -95,12 +95,12 @@ notmuch_message_close (notmuch_message_t *message);
  * returned even if that header exists in the actual message.
  */
 void
-notmuch_message_restrict_headers (notmuch_message_t *message, ...);
+notmuch_message_file_restrict_headers (notmuch_message_file_t *message, ...);
 
 /* Identical to notmuch_message_restrict_headers but accepting a va_list. */
 void
-notmuch_message_restrict_headersv (notmuch_message_t *message,
-                                  va_list va_headers);
+notmuch_message_file_restrict_headersv (notmuch_message_file_t *message,
+                                       va_list va_headers);
 
 /* Get the value of the specified header from the message.
  *
@@ -114,8 +114,8 @@ notmuch_message_restrict_headersv (notmuch_message_t *message,
  * 'header'.
  */
 const char *
-notmuch_message_get_header (notmuch_message_t *message,
-                           const char *header);
+notmuch_message_file_get_header (notmuch_message_file_t *message,
+                                const char *header);
 
 /* date.c */