Xapian::Document doc;
};
-struct _notmuch_tags {
+typedef struct _notmuch_terms {
+ char prefix_char;
Xapian::TermIterator iterator;
Xapian::TermIterator iterator_end;
+} notmuch_terms_t;
+
+struct _notmuch_tags {
+ notmuch_terms_t terms;
};
struct _notmuch_thread_ids {
- char *current;
- char *next;
+ notmuch_terms_t terms;
};
/* "128 bits of thread-id ought to be enough for anybody" */
* talloc_set_destructor at all otherwise).
*/
static int
-_notmuch_tags_destructor (notmuch_tags_t *tags)
+_notmuch_terms_destructor (notmuch_terms_t *terms)
{
- tags->iterator.~TermIterator ();
- tags->iterator_end.~TermIterator ();
+ terms->iterator.~TermIterator ();
+ terms->iterator_end.~TermIterator ();
return 0;
}
-notmuch_tags_t *
-notmuch_message_get_tags (notmuch_message_t *message)
+notmuch_terms_t *
+_notmuch_terms_create (void *ctx,
+ Xapian::Document doc,
+ const char *prefix_name)
{
- notmuch_tags_t *tags;
+ notmuch_terms_t *terms;
+ const char *prefix = _find_prefix (prefix_name);
+
+ /* Currently, notmuch_terms_t is written with the assumption that
+ * any prefix its derivatives use will be only a single
+ * character. */
+ assert (strlen (prefix) == 1);
- tags = talloc (message, notmuch_tags_t);
- if (unlikely (tags == NULL))
+ terms = talloc (ctx, notmuch_terms_t);
+ if (unlikely (terms == NULL))
return NULL;
- new (&tags->iterator) Xapian::TermIterator;
- new (&tags->iterator_end) Xapian::TermIterator;
+ terms->prefix_char = *prefix;
+ new (&terms->iterator) Xapian::TermIterator;
+ new (&terms->iterator_end) Xapian::TermIterator;
- talloc_set_destructor (tags, _notmuch_tags_destructor);
+ talloc_set_destructor (terms, _notmuch_terms_destructor);
- tags->iterator = message->doc.termlist_begin ();
- tags->iterator.skip_to (_find_prefix ("tag"));
- tags->iterator_end = message->doc.termlist_end ();
+ terms->iterator = doc.termlist_begin ();
+ terms->iterator.skip_to (prefix);
+ terms->iterator_end = doc.termlist_end ();
- return tags;
+ return terms;
+}
+
+/* The assertion is to ensure that 'type' is a derivative of
+ * notmuch_terms_t in that it contains a notmuch_terms_t as its first
+ * member. We do this by name of 'terms' as opposed to type, because
+ * that's as clever as I've been so far. */
+#define _notmuch_terms_create_type(ctx, doc, prefix_name, type) \
+ (COMPILE_TIME_ASSERT(offsetof(type, terms) == 0), \
+ (type *) _notmuch_terms_create (ctx, doc, prefix_name))
+
+notmuch_tags_t *
+notmuch_message_get_tags (notmuch_message_t *message)
+{
+ return _notmuch_terms_create_type (message, message->doc, "tag",
+ notmuch_tags_t);
}
notmuch_thread_ids_t *
notmuch_message_get_thread_ids (notmuch_message_t *message)
{
- notmuch_thread_ids_t *thread_ids;
- std::string id_str;
-
- thread_ids = talloc (message, notmuch_thread_ids_t);
- if (unlikely (thread_ids == NULL))
- return NULL;
-
- id_str = message->doc.get_value (NOTMUCH_VALUE_THREAD);
- thread_ids->next = talloc_strdup (message, id_str.c_str ());
-
- /* Initialize thread_ids->current and terminate first ID. */
- notmuch_thread_ids_advance (thread_ids);
-
- return thread_ids;
+ return _notmuch_terms_create_type (message, message->doc, "thread",
+ notmuch_thread_ids_t);
}
void
_notmuch_message_add_thread_id (notmuch_message_t *message,
const char *thread_id)
{
- std::string id_str;
-
_notmuch_message_add_term (message, "thread", thread_id);
-
- id_str = message->doc.get_value (NOTMUCH_VALUE_THREAD);
-
- if (id_str.empty ()) {
- message->doc.add_value (NOTMUCH_VALUE_THREAD, thread_id);
- } else {
- size_t pos;
-
- /* Think about using a hash here if there's any performance
- * problem. */
- pos = id_str.find (thread_id);
- if (pos == std::string::npos) {
- id_str.append (",");
- id_str.append (thread_id);
- message->doc.add_value (NOTMUCH_VALUE_THREAD, id_str);
- }
- }
}
static void
thread_id_generate (&thread_id);
_notmuch_message_add_term (message, "thread", thread_id.str);
- message->doc.add_value (NOTMUCH_VALUE_THREAD, thread_id.str);
}
/* Synchronize changes made to message->doc out into the database. */
}
notmuch_bool_t
-notmuch_tags_has_more (notmuch_tags_t *tags)
+_notmuch_terms_has_more (notmuch_terms_t *terms)
{
std::string s;
- if (tags->iterator == tags->iterator_end)
+ if (terms->iterator == terms->iterator_end)
return FALSE;
- s = *tags->iterator;
- if (! s.empty () && s[0] == 'L')
+ s = *terms->iterator;
+ if (! s.empty () && s[0] == terms->prefix_char)
return TRUE;
else
return FALSE;
}
+const char *
+_notmuch_terms_get (notmuch_terms_t *terms)
+{
+ return talloc_strdup (terms, (*terms->iterator).c_str () + 1);
+}
+
+void
+_notmuch_terms_advance (notmuch_terms_t *terms)
+{
+ terms->iterator++;
+}
+
+void
+_notmuch_terms_destroy (notmuch_terms_t *terms)
+{
+ talloc_free (terms);
+}
+
+notmuch_bool_t
+notmuch_tags_has_more (notmuch_tags_t *tags)
+{
+ return _notmuch_terms_has_more (&tags->terms);
+}
+
const char *
notmuch_tags_get (notmuch_tags_t *tags)
{
- return talloc_strdup (tags, (*tags->iterator).c_str () + 1);
+ return _notmuch_terms_get (&tags->terms);
}
void
notmuch_tags_advance (notmuch_tags_t *tags)
{
- tags->iterator++;
+ return _notmuch_terms_advance (&tags->terms);
}
void
notmuch_tags_destroy (notmuch_tags_t *tags)
{
- talloc_free (tags);
+ return _notmuch_terms_destroy (&tags->terms);
}
notmuch_bool_t
notmuch_thread_ids_has_more (notmuch_thread_ids_t *thread_ids)
{
- if (thread_ids->current == NULL || *thread_ids->current == '\0')
- return FALSE;
- else
- return TRUE;
+ return _notmuch_terms_has_more (&thread_ids->terms);
}
const char *
notmuch_thread_ids_get (notmuch_thread_ids_t *thread_ids)
{
- return thread_ids->current;
+ return _notmuch_terms_get (&thread_ids->terms);
}
void
notmuch_thread_ids_advance (notmuch_thread_ids_t *thread_ids)
{
- thread_ids->current = strsep (&thread_ids->next, ",");
+ return _notmuch_terms_advance (&thread_ids->terms);
}
void
notmuch_thread_ids_destroy (notmuch_thread_ids_t *thread_ids)
{
- talloc_free (thread_ids);
+ return _notmuch_terms_destroy (&thread_ids->terms);
}