* 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/ .
+ * along with this program. If not, see https://www.gnu.org/licenses/ .
*
* Author: Carl Worth <cworth@cworth.org>
*/
#include <talloc.h>
+#include "gmime-extra.h"
+
#include "xutil.h"
#include "error_util.h"
-
-#pragma GCC visibility push(hidden)
+#include "string-util.h"
#ifdef DEBUG
# define DEBUG_DATABASE_SANITY 1
#define STRNCMP_LITERAL(var, literal) \
strncmp ((var), (literal), sizeof (literal) - 1)
-#define unused(x) x __attribute__ ((unused))
+/* Robust bit test/set/reset macros */
+#define _NOTMUCH_VALID_BIT(bit) \
+ ((bit) >= 0 && ((unsigned long) bit) < CHAR_BIT * sizeof (unsigned long long))
+#define NOTMUCH_TEST_BIT(val, bit) \
+ (_NOTMUCH_VALID_BIT(bit) ? !!((val) & (1ull << (bit))) : 0)
+#define NOTMUCH_SET_BIT(valp, bit) \
+ (_NOTMUCH_VALID_BIT(bit) ? (*(valp) |= (1ull << (bit))) : *(valp))
+#define NOTMUCH_CLEAR_BIT(valp, bit) \
+ (_NOTMUCH_VALID_BIT(bit) ? (*(valp) &= ~(1ull << (bit))) : *(valp))
-#ifdef __cplusplus
-# define visible __attribute__((visibility("default")))
-#else
-# define visible
-#endif
+#define unused(x) x __attribute__ ((unused))
/* Thanks to Andrew Tridgell's (SAMBA's) talloc for this definition of
* unlikely. The talloc source code comes to us via the GNU LGPL v. 3.
NOTMUCH_VALUE_TIMESTAMP = 0,
NOTMUCH_VALUE_MESSAGE_ID,
NOTMUCH_VALUE_FROM,
- NOTMUCH_VALUE_SUBJECT
+ NOTMUCH_VALUE_SUBJECT,
+ NOTMUCH_VALUE_LAST_MOD,
} notmuch_value_t;
/* Xapian (with flint backend) complains if we provide a term longer
* to or greater than NOTMUCH_STATUS_LAST_STATUS. (The idea here is
* that the caller has previously handled any expected
* notmuch_private_status_t values.)
+ *
+ * Note that the function _internal_error does not return. Evaluating
+ * to NOTMUCH_STATUS_SUCCESS is done purely to appease the compiler.
*/
#define COERCE_STATUS(private_status, format, ...) \
((private_status >= (notmuch_private_status_t) NOTMUCH_STATUS_LAST_STATUS)\
? \
- (notmuch_status_t) _internal_error (format " (%s).\n", \
- ##__VA_ARGS__, \
- __location__) \
+ _internal_error (format " (%s).\n", \
+ ##__VA_ARGS__, \
+ __location__), \
+ (notmuch_status_t) NOTMUCH_PRIVATE_STATUS_SUCCESS \
: \
(notmuch_status_t) private_status)
-typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t;
+/* Flags shared by various lookup functions. */
+typedef enum _notmuch_find_flags {
+ /* Lookup without creating any documents. This is the default
+ * behavior. */
+ NOTMUCH_FIND_LOOKUP = 0,
+ /* If set, create the necessary document (or documents) if they
+ * are missing. Requires a read/write database. */
+ NOTMUCH_FIND_CREATE = 1<<0,
+} notmuch_find_flags_t;
-typedef struct _notmuch_string_list notmuch_string_list_t;
+typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t;
/* database.cc */
const char *
_find_prefix (const char *name);
+char *
+_notmuch_message_id_compressed (void *ctx, const char *message_id);
+
notmuch_status_t
_notmuch_database_ensure_writable (notmuch_database_t *notmuch);
+notmuch_status_t
+_notmuch_database_reopen (notmuch_database_t *notmuch);
+
+void
+_notmuch_database_log (notmuch_database_t *notmuch,
+ const char *format, ...);
+
+void
+_notmuch_database_log_append (notmuch_database_t *notmuch,
+ const char *format, ...);
+
+unsigned long
+_notmuch_database_new_revision (notmuch_database_t *notmuch);
+
const char *
_notmuch_database_relative_path (notmuch_database_t *notmuch,
const char *path);
notmuch_status_t
_notmuch_database_find_directory_id (notmuch_database_t *database,
const char *path,
+ notmuch_find_flags_t flags,
unsigned int *directory_id);
const char *
_notmuch_database_filename_to_direntry (void *ctx,
notmuch_database_t *notmuch,
const char *filename,
+ notmuch_find_flags_t flags,
char **direntry);
/* directory.cc */
notmuch_directory_t *
_notmuch_directory_create (notmuch_database_t *notmuch,
const char *path,
+ notmuch_find_flags_t flags,
notmuch_status_t *status_ret);
unsigned int
_notmuch_directory_get_document_id (notmuch_directory_t *directory);
-/* thread.cc */
-
-notmuch_thread_t *
-_notmuch_thread_create (void *ctx,
- notmuch_database_t *notmuch,
- unsigned int seed_doc_id,
- notmuch_doc_id_set_t *match_set,
- notmuch_string_list_t *excluded_terms,
- notmuch_sort_t sort);
-
/* message.cc */
notmuch_message_t *
const char *prefix_name,
const char *value);
+notmuch_private_status_t
+_notmuch_message_has_term (notmuch_message_t *message,
+ const char *prefix_name,
+ const char *value,
+ notmuch_bool_t *result);
+
notmuch_private_status_t
_notmuch_message_gen_terms (notmuch_message_t *message,
const char *prefix_name,
void
_notmuch_message_upgrade_filename_storage (notmuch_message_t *message);
+void
+_notmuch_message_upgrade_folder (notmuch_message_t *message);
+
notmuch_status_t
_notmuch_message_add_filename (notmuch_message_t *message,
const char *filename);
const char *date,
const char *from,
const char *subject);
+
+void
+_notmuch_message_upgrade_last_mod (notmuch_message_t *message);
+
void
_notmuch_message_sync (notmuch_message_t *message);
notmuch_status_t
_notmuch_message_delete (notmuch_message_t *message);
+notmuch_private_status_t
+_notmuch_message_initialize_ghost (notmuch_message_t *message,
+ const char *thread_id);
+
void
_notmuch_message_close (notmuch_message_t *message);
/* Set the author member of 'message' - this is the representation used
* when displaying the message */
void
-notmuch_message_set_author (notmuch_message_t *message, const char *author);
+_notmuch_message_set_author (notmuch_message_t *message, const char *author);
/* Get the author member of 'message' */
const char *
-notmuch_message_get_author (notmuch_message_t *message);
-
-
-/* index.cc */
-
-notmuch_status_t
-_notmuch_message_index_file (notmuch_message_t *message,
- const char *filename);
+_notmuch_message_get_author (notmuch_message_t *message);
/* message-file.c */
* Returns NULL if any error occurs.
*/
notmuch_message_file_t *
-notmuch_message_file_open (const char *filename);
+_notmuch_message_file_open (notmuch_database_t *notmuch, const char *filename);
/* Like notmuch_message_file_open but with 'ctx' as the talloc owner. */
notmuch_message_file_t *
-_notmuch_message_file_open_ctx (void *ctx, const char *filename);
+_notmuch_message_file_open_ctx (notmuch_database_t *notmuch,
+ void *ctx, const char *filename);
/* Close a notmuch message previously opened with notmuch_message_open. */
void
-notmuch_message_file_close (notmuch_message_file_t *message);
+_notmuch_message_file_close (notmuch_message_file_t *message);
-/* Restrict 'message' to only save the named headers.
+/* Parse the message.
*
- * When the caller is only interested in a short list of headers,
- * known in advance, calling this function can avoid wasted time and
- * memory parsing/saving header values that will never be needed.
+ * This will be done automatically as necessary on other calls
+ * depending on it, but an explicit call allows for better error
+ * status reporting.
+ */
+notmuch_status_t
+_notmuch_message_file_parse (notmuch_message_file_t *message);
+
+/* Get the gmime message of a message file.
*
- * The variable arguments should be a list of const char * with a
- * final '(const char *) NULL' to terminate the list.
+ * The message file is parsed as necessary.
*
- * If this function is called, it must be called before any calls to
- * notmuch_message_get_header for this message.
+ * The GMimeMessage* is set to *mime_message on success (which the
+ * caller must not unref).
*
- * After calling this function, if notmuch_message_get_header is
- * called with a header name not in this list, then NULL will be
- * returned even if that header exists in the actual message.
+ * XXX: Would be nice to not have to expose GMimeMessage here.
*/
-void
-notmuch_message_file_restrict_headers (notmuch_message_file_t *message, ...);
-
-/* Identical to notmuch_message_restrict_headers but accepting a va_list. */
-void
-notmuch_message_file_restrict_headersv (notmuch_message_file_t *message,
- va_list va_headers);
+notmuch_status_t
+_notmuch_message_file_get_mime_message (notmuch_message_file_t *message,
+ GMimeMessage **mime_message);
-/* Get the value of the specified header from the message.
+/* Get the value of the specified header from the message as a UTF-8 string.
+ *
+ * The message file is parsed as necessary.
*
* The header name is case insensitive.
*
* only until the message is closed. The caller should copy it if
* needing to modify the value or to hold onto it for longer.
*
- * Returns NULL if the message does not contain a header line matching
- * 'header'.
+ * Returns NULL on errors, empty string if the message does not
+ * contain a header line matching 'header'.
*/
const char *
-notmuch_message_file_get_header (notmuch_message_file_t *message,
+_notmuch_message_file_get_header (notmuch_message_file_t *message,
const char *header);
+/* index.cc */
+
+notmuch_status_t
+_notmuch_message_index_file (notmuch_message_t *message,
+ notmuch_message_file_t *message_file);
+
/* messages.c */
typedef struct _notmuch_message_node {
* somewhere with some nasty C++ objects in it. We'll try to maintain
* ignorance of that here. (See notmuch_mset_messages_t in query.cc)
*/
-struct visible _notmuch_messages {
+struct _notmuch_messages {
notmuch_bool_t is_of_list_type;
notmuch_doc_id_set_t *excluded_doc_ids;
notmuch_message_node_t *iterator;
notmuch_message_list_t *
_notmuch_message_list_create (const void *ctx);
-void
-_notmuch_message_list_append (notmuch_message_list_t *list,
- notmuch_message_node_t *node);
-
void
_notmuch_message_list_add_message (notmuch_message_list_t *list,
notmuch_message_t *message);
notmuch_bool_t
_notmuch_doc_id_set_contains (notmuch_doc_id_set_t *doc_ids,
- unsigned int doc_id);
+ unsigned int doc_id);
void
_notmuch_doc_id_set_remove (notmuch_doc_id_set_t *doc_ids,
- unsigned int doc_id);
+ unsigned int doc_id);
+
+/* querying xapian documents by type (e.g. "mail" or "ghost"): */
+notmuch_status_t
+_notmuch_query_search_documents (notmuch_query_t *query,
+ const char *type,
+ notmuch_messages_t **out);
+
+notmuch_status_t
+_notmuch_query_count_documents (notmuch_query_t *query,
+ const char *type,
+ unsigned *count_out);
/* message.cc */
void
_notmuch_message_add_reply (notmuch_message_t *message,
- notmuch_message_node_t *reply);
+ notmuch_message_t *reply);
+notmuch_database_t *
+_notmuch_message_database (notmuch_message_t *message);
/* sha1.c */
char *
-notmuch_sha1_of_string (const char *str);
+_notmuch_sha1_of_string (const char *str);
char *
-notmuch_sha1_of_file (const char *filename);
+_notmuch_sha1_of_file (const char *filename);
/* string-list.c */
struct _notmuch_string_node *next;
} notmuch_string_node_t;
-struct visible _notmuch_string_list {
+typedef struct _notmuch_string_list {
int length;
notmuch_string_node_t *head;
notmuch_string_node_t **tail;
-};
+} notmuch_string_list_t;
notmuch_string_list_t *
_notmuch_string_list_create (const void *ctx);
void
_notmuch_string_list_sort (notmuch_string_list_t *list);
+/* string-map.c */
+typedef struct _notmuch_string_map notmuch_string_map_t;
+typedef struct _notmuch_string_map_iterator notmuch_string_map_iterator_t;
+notmuch_string_map_t *
+_notmuch_string_map_create (const void *ctx);
+
+void
+_notmuch_string_map_append (notmuch_string_map_t *map,
+ const char *key,
+ const char *value);
+
+const char *
+_notmuch_string_map_get (notmuch_string_map_t *map, const char *key);
+
+notmuch_string_map_iterator_t *
+_notmuch_string_map_iterator_create (notmuch_string_map_t *map, const char *key,
+ notmuch_bool_t exact);
+
+notmuch_bool_t
+_notmuch_string_map_iterator_valid (notmuch_string_map_iterator_t *iter);
+
+void
+_notmuch_string_map_iterator_move_to_next (notmuch_string_map_iterator_t *iter);
+
+const char *
+_notmuch_string_map_iterator_key (notmuch_string_map_iterator_t *iterator);
+
+const char *
+_notmuch_string_map_iterator_value (notmuch_string_map_iterator_t *iterator);
+
+void
+_notmuch_string_map_iterator_destroy (notmuch_string_map_iterator_t *iterator);
+
/* tags.c */
notmuch_tags_t *
_notmuch_filenames_create (const void *ctx,
notmuch_string_list_t *list);
-#pragma GCC visibility pop
+/* thread.cc */
+
+notmuch_thread_t *
+_notmuch_thread_create (void *ctx,
+ notmuch_database_t *notmuch,
+ unsigned int seed_doc_id,
+ notmuch_doc_id_set_t *match_set,
+ notmuch_string_list_t *excluded_terms,
+ notmuch_exclude_t omit_exclude,
+ notmuch_sort_t sort);
NOTMUCH_END_DECLS
+#ifdef __cplusplus
+/* Implicit typecast from 'void *' to 'T *' is okay in C, but not in
+ * C++. In talloc_steal, an explicit cast is provided for type safety
+ * in some GCC versions. Otherwise, a cast is required. Provide a
+ * template function for this to maintain type safety, and redefine
+ * talloc_steal to use it.
+ */
+#if !(__GNUC__ >= 3)
+template <class T> T *
+_notmuch_talloc_steal (const void *new_ctx, const T *ptr)
+{
+ return static_cast<T *> (talloc_steal (new_ctx, ptr));
+}
+#undef talloc_steal
+#define talloc_steal _notmuch_talloc_steal
+#endif
+#endif
+
#endif