With essentially the same code path, we can provide a key/value lookup facility, for future use. --- lib/message.cc | 68 ++++++++++++++++++++++++++++++++++++++++----------- lib/notmuch-private.h | 6 +++++ 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/lib/message.cc b/lib/message.cc index 6839305..90c2bb2 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -1263,36 +1263,76 @@ _notmuch_message_remove_term (notmuch_message_t *message, return NOTMUCH_PRIVATE_STATUS_SUCCESS; } +/* + * look for a term with given prefix. If value != NULL, return the + * suffix of the first such term. If suffix == NULL, consider any + * non-empty suffix a mismatch +*/ +notmuch_private_status_t +_notmuch_message_get_prefixed_term (notmuch_message_t *message, + const char *prefix, + const char **value) +{ + notmuch_private_status_t status = NOTMUCH_PRIVATE_STATUS_SUCCESS; + + if (strlen (prefix) > NOTMUCH_TERM_MAX) + return NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG; + + try { + /* Look for prefixed term */ + Xapian::TermIterator i = message->doc.termlist_begin (); + i.skip_to (prefix); + if ((i == message->doc.termlist_end ()) || + (strncmp (prefix, (*i).c_str (), strlen(prefix)) != 0)) { + status = NOTMUCH_PRIVATE_STATUS_NO_TERM_FOUND; + } else { + std::string suffix = (*i).substr (strlen (prefix)); + if (value) { + *value = talloc_strdup (message, suffix.c_str ()); + } else { + /* non-exact match considered failure */ + if (suffix.length () > 0) + status = NOTMUCH_PRIVATE_STATUS_NO_TERM_FOUND; + } + } + } catch (Xapian::Error &error) { + status = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION; + } + + return status; +} + notmuch_private_status_t _notmuch_message_has_term (notmuch_message_t *message, const char *prefix_name, const char *value, notmuch_bool_t *result) { + notmuch_bool_t out = TRUE; + notmuch_private_status_t status; char *term; - notmuch_bool_t out = FALSE; - notmuch_private_status_t status = NOTMUCH_PRIVATE_STATUS_SUCCESS; if (value == NULL) return NOTMUCH_PRIVATE_STATUS_NULL_POINTER; + term = talloc_asprintf (message, "%s%s", _find_prefix (prefix_name), value); - if (strlen (term) > NOTMUCH_TERM_MAX) - return NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG; + if (term == NULL) { + status = NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY; + goto DONE; + } - try { - /* Look for the exact term */ - Xapian::TermIterator i = message->doc.termlist_begin (); - i.skip_to (term); - if (i != message->doc.termlist_end () && - !strcmp ((*i).c_str (), term)) - out = TRUE; - } catch (Xapian::Error &error) { - status = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION; + status = _notmuch_message_get_prefixed_term (message, term, NULL); + if (status == NOTMUCH_PRIVATE_STATUS_NO_TERM_FOUND) { + status = NOTMUCH_PRIVATE_STATUS_SUCCESS; + out = FALSE; } - talloc_free (term); + + DONE: + if (term) + talloc_free (term); *result = out; return status; diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 9280797..f7eba4a 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -141,6 +141,7 @@ typedef enum _notmuch_private_status { /* Then add our own private values. */ NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG = NOTMUCH_STATUS_LAST_STATUS, NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND, + NOTMUCH_PRIVATE_STATUS_NO_TERM_FOUND, NOTMUCH_PRIVATE_STATUS_LAST_STATUS } notmuch_private_status_t; @@ -333,6 +334,11 @@ _notmuch_message_initialize_ghost (notmuch_message_t *message, void _notmuch_message_close (notmuch_message_t *message); +notmuch_private_status_t +_notmuch_message_get_prefixed_term (notmuch_message_t *message, + const char *prefix, + const char **suffix); + /* Get a copy of the data in this message document. * * Caller should talloc_free the result when done. -- 2.8.1