From ce46c44ea917bdd51c9805648d89e04b4e34c53d Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 21 May 2022 17:42:25 +0300 Subject: [PATCH] query-results: ease getting Xapian::Document for iter This makes it easier to construct guile-usable Messages. --- lib/mu-query-results.hh | 111 ++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/lib/mu-query-results.hh b/lib/mu-query-results.hh index 2505eca8..d66ee2c5 100644 --- a/lib/mu-query-results.hh +++ b/lib/mu-query-results.hh @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -177,7 +178,7 @@ public: */ QueryResultsIterator& operator++() { ++mset_it_; - document_.reset(); + mdoc_ = Nothing; return *this; } @@ -194,19 +195,39 @@ public: QueryResultsIterator& operator*() { return *this; } const QueryResultsIterator& operator*() const { return *this; } + /** - * Get the Mu::Document this iterator is pointing at, + * Get the Xapian::Document this iterator is pointing at, * or an empty document when looking at end(). * * @return a document */ - const Mu::Document& document() const { - if (!document_) - document_.emplace(mset_it_.get_document()); - return *document_; + Option document() const { + return xapian_try([this]()->Option { + auto doc{mset_it_.get_document()}; + if (doc.get_docid() == 0) + return Nothing; + else + return Some(std::move(doc)); + }, Nothing); } + /** + * get the corresponding Message for this iter, if any + * + * @return a Message or Nothing + */ + Option message() const { + if (auto&& xdoc{document()}; !xdoc) + return Nothing; + else if (auto&& doc{Message::make_from_document(std::move(xdoc.value()))}; + !doc) + return Nothing; + else + return Some(std::move(doc.value())); + } + /** * Get the doc-id for the document this iterator is pointing at, or 0 * when looking at end. @@ -221,8 +242,7 @@ public: * * @return a message-id */ - Option message_id() const noexcept - { + Option message_id() const noexcept { return opt_string(Field::Id::MessageId); } @@ -232,8 +252,7 @@ public: * * @return a message-id */ - Option thread_id() const noexcept - { + Option thread_id() const noexcept { return opt_string(Field::Id::ThreadId); } @@ -243,7 +262,9 @@ public: * * @return a filesystem path */ - Option path() const noexcept { return opt_string(Field::Id::Path); } + Option path() const noexcept { + return opt_string(Field::Id::Path); + } /** * Get the date for the document (message) the iterator is pointing at. @@ -251,7 +272,9 @@ public: * * @return a filesystem path */ - Option date() const noexcept { return opt_string(Field::Id::Date); } + Option date() const noexcept { + return opt_string(Field::Id::Date); + } /** * Get the file-system path for the document (message) this iterator is @@ -259,7 +282,9 @@ public: * * @return the subject */ - Option subject() const noexcept { return opt_string(Field::Id::Subject); } + Option subject() const noexcept { + return opt_string(Field::Id::Subject); + } /** * Get the references for the document (messages) this is iterator is @@ -269,7 +294,7 @@ public: * @return references */ std::vector references() const noexcept { - return document().string_vec_value(Field::Id::References); + return mu_document().string_vec_value(Field::Id::References); } /** @@ -280,7 +305,7 @@ public: * @return the value */ Option opt_string(Field::Id id) const noexcept { - if (auto&& val{document().string_value(id)}; val.empty()) + if (auto&& val{mu_document().string_value(id)}; val.empty()) return Nothing; else return Some(std::move(val)); @@ -292,48 +317,34 @@ public: * @return the match info. */ QueryMatch& query_match() { - g_assert(query_matches_.find(document().docid()) != query_matches_.end()); - return query_matches_.find(document().docid())->second; + g_assert(query_matches_.find(doc_id()) != query_matches_.end()); + return query_matches_.find(doc_id())->second; } const QueryMatch& query_match() const { - g_assert(query_matches_.find(document().docid()) != query_matches_.end()); - return query_matches_.find(document().docid())->second; + g_assert(query_matches_.find(doc_id()) != query_matches_.end()); + return query_matches_.find(doc_id())->second; } - /** - * get the corresponding Message for this iter - * - * @return a Message or Nothing - */ - Option message() const { - return xapian_try( - [&]()->Option { - auto msg{Message::make_from_document(mset_it_.get_document())}; - if (msg) - return Some(std::move(msg.value())); - else - return Nothing; - }, - Nothing); - } - - /** - * get the corresponding Message for this iter a heap-allocated ptr; - * - * @return a unique ptr to a Message or P{} - */ - std::unique_ptr unique_message_ptr() const { - return xapian_try( - [&]()->std::unique_ptr { - return std::make_unique(mset_it_.get_document()); - }, nullptr); - } - - private: + /** + * Get a (cached) reference for the Mu::Document corresponding + * to the current iter. + * + * @return cached mu document, + */ + const Mu::Document& mu_document() const { + if (!mdoc_) { + if (auto xdoc = document(); !xdoc) + std::runtime_error("iter without document"); + else + mdoc_ = Mu::Document{xdoc.value()}; + } + return mdoc_.value(); + } + + mutable Option mdoc_; // cache. Xapian::MSetIterator mset_it_; QueryMatches& query_matches_; - mutable Option document_; }; constexpr auto MaxQueryResultsSize = std::numeric_limits::max();