The rough idea is to give a C interface to the Xapian::TermIterator class. --- lib/metadata.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/notmuch.h | 12 ++++++++++ test/T590-metadata.sh | 15 ++++++++++++ 3 files changed, 90 insertions(+) diff --git a/lib/metadata.cc b/lib/metadata.cc index a068ed1..5d319c5 100644 --- a/lib/metadata.cc +++ b/lib/metadata.cc @@ -22,6 +22,17 @@ #include "notmuch-private.h" #include "database-private.h" +struct _notmuch_metadata { + notmuch_database_t *notmuch; + Xapian::TermIterator *iterator; + notmuch_metadata_class_t mclass; +}; + +static int +_notmuch_metadata_destroy (notmuch_metadata_t *list) { + delete list->iterator; + return 0; +} static const char * _find_metadata_prefix (notmuch_metadata_class_t mclass) @@ -148,3 +159,55 @@ notmuch_database_get_metadata (notmuch_database_t *notmuch, return NOTMUCH_STATUS_SUCCESS; } + +notmuch_status_t +notmuch_database_get_all_metadata (notmuch_database_t *notmuch, + notmuch_metadata_class_t mclass, + notmuch_metadata_t **out) +{ + notmuch_metadata_t *list = NULL; + notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; + + const char *prefix = _find_metadata_prefix (mclass); + + list = talloc (notmuch, notmuch_metadata_t); + if (!list) { + status = NOTMUCH_STATUS_OUT_OF_MEMORY; + goto DONE; + } + + talloc_set_destructor(list, _notmuch_metadata_destroy); + list->iterator = new Xapian::TermIterator; + list->notmuch = notmuch; + list->mclass = mclass; + + try { + + *list->iterator = notmuch->xapian_db->metadata_keys_begin(); + list->iterator->skip_to (prefix); + + } catch (const Xapian::Error &error) { + _notmuch_database_log (notmuch, "A Xapian exception occurred getting metadata iterator: %s.\n", + error.get_msg().c_str()); + notmuch->exception_reported = TRUE; + status = NOTMUCH_STATUS_XAPIAN_EXCEPTION; + } + + *out = list; + + DONE: + if (status && list) + talloc_free (list); + + return status; +} + +notmuch_bool_t +notmuch_metadata_valid (notmuch_metadata_t *metadata) +{ + const char *prefix = _find_metadata_prefix (metadata->mclass); + if (*(metadata->iterator) == metadata->notmuch->xapian_db->metadata_keys_end()) + return FALSE; + + return (strncmp((**(metadata->iterator)).c_str (), prefix, strlen (prefix)) == 0); +} diff --git a/lib/notmuch.h b/lib/notmuch.h index 448f405..a2b7040 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -197,6 +197,7 @@ typedef struct _notmuch_message notmuch_message_t; typedef struct _notmuch_tags notmuch_tags_t; typedef struct _notmuch_directory notmuch_directory_t; typedef struct _notmuch_filenames notmuch_filenames_t; +typedef struct _notmuch_metadata notmuch_metadata_t; #endif /* __DOXYGEN__ */ /** @@ -1854,6 +1855,17 @@ notmuch_database_set_metadata (notmuch_database_t *db, notmuch_metadata_class_t notmuch_status_t notmuch_database_get_metadata (notmuch_database_t *db, notmuch_metadata_class_t mclass, const char *key, char **value); +/** + * get all metadata of a given class + */ +notmuch_status_t +notmuch_database_get_all_metadata (notmuch_database_t *db, notmuch_metadata_class_t mclass, notmuch_metadata_t **out); + +/** + * Is 'metadata' iterator valid (i.e. _key, _value, _move_to_next can be called). + */ +notmuch_bool_t +notmuch_metadata_valid (notmuch_metadata_t *metadata); /* @} */ NOTMUCH_END_DECLS diff --git a/test/T590-metadata.sh b/test/T590-metadata.sh index 29aeaa2..c36a7d7 100755 --- a/test/T590-metadata.sh +++ b/test/T590-metadata.sh @@ -55,4 +55,19 @@ testkey2 = testvalue2 EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "notmuch_database_get_all_metadata initially valid" +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} +{ + notmuch_metadata_t *meta; + RUN(notmuch_database_get_all_metadata (db, NOTMUCH_METADATA_CONFIG, &meta)); + printf("valid = %d\n", notmuch_metadata_valid (meta)); +} +EOF +cat <<'EOF' >EXPECTED +== stdout == +valid = 1 +== stderr == +EOF +test_expect_equal_file EXPECTED OUTPUT + test_done -- 2.6.4