1 /* message-property.cc - Properties are like tags, but (key,value) pairs.
2 * keys are allowed to repeat.
4 * This file is part of notmuch.
6 * Copyright © 2016 David Bremner
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses/ .
21 * Author: David Bremner <david@tethera.net>
24 #include "notmuch-private.h"
25 #include "database-private.h"
26 #include "message-private.h"
28 #define LOG_XAPIAN_EXCEPTION(message, error) _log_xapian_exception (__location__, message, error)
31 _log_xapian_exception (const char *where, notmuch_message_t *message, const Xapian::Error error)
33 notmuch_database_t *notmuch = notmuch_message_get_database (message);
35 _notmuch_database_log (notmuch,
36 "A Xapian exception occurred at %s: %s\n",
38 error.get_msg ().c_str ());
39 notmuch->exception_reported = true;
43 notmuch_message_get_property (notmuch_message_t *message, const char *key, const char **value)
46 return NOTMUCH_STATUS_NULL_POINTER;
48 *value = _notmuch_string_map_get (_notmuch_message_property_map (message), key);
50 return NOTMUCH_STATUS_SUCCESS;
54 notmuch_message_count_properties (notmuch_message_t *message, const char *key, unsigned int *count)
56 if (! count || ! key || ! message)
57 return NOTMUCH_STATUS_NULL_POINTER;
59 notmuch_string_map_t *map;
61 map = _notmuch_message_property_map (message);
63 return NOTMUCH_STATUS_NULL_POINTER;
65 notmuch_string_map_iterator_t *matcher = _notmuch_string_map_iterator_create (map, key, true);
68 return NOTMUCH_STATUS_OUT_OF_MEMORY;
71 while (_notmuch_string_map_iterator_valid (matcher)) {
73 _notmuch_string_map_iterator_move_to_next (matcher);
76 _notmuch_string_map_iterator_destroy (matcher);
77 return NOTMUCH_STATUS_SUCCESS;
80 static notmuch_status_t
81 _notmuch_message_modify_property (notmuch_message_t *message, const char *key, const char *value,
84 notmuch_private_status_t private_status;
85 notmuch_status_t status;
88 status = _notmuch_database_ensure_writable (notmuch_message_get_database (message));
92 if (key == NULL || value == NULL)
93 return NOTMUCH_STATUS_NULL_POINTER;
95 if (strchr (key, '='))
96 return NOTMUCH_STATUS_ILLEGAL_ARGUMENT;
98 term = talloc_asprintf (message, "%s=%s", key, value);
102 private_status = _notmuch_message_remove_term (message, "property", term);
104 private_status = _notmuch_message_add_term (message, "property", term);
105 } catch (Xapian::Error &error) {
106 LOG_XAPIAN_EXCEPTION (message, error);
107 return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
111 return COERCE_STATUS (private_status,
112 "Unhandled error modifying message property");
113 if (! _notmuch_message_frozen (message))
114 _notmuch_message_sync (message);
119 return NOTMUCH_STATUS_SUCCESS;
123 notmuch_message_add_property (notmuch_message_t *message, const char *key, const char *value)
125 return _notmuch_message_modify_property (message, key, value, false);
129 notmuch_message_remove_property (notmuch_message_t *message, const char *key, const char *value)
131 return _notmuch_message_modify_property (message, key, value, true);
136 _notmuch_message_remove_all_properties (notmuch_message_t *message, const char *key, bool prefix)
138 notmuch_status_t status;
139 const char *term_prefix;
141 status = _notmuch_database_ensure_writable (notmuch_message_get_database (message));
146 term_prefix = talloc_asprintf (message, "%s%s%s", _find_prefix ("property"), key,
149 term_prefix = _find_prefix ("property");
152 /* XXX better error reporting ? */
153 _notmuch_message_remove_terms (message, term_prefix);
154 } catch (Xapian::Error &error) {
155 LOG_XAPIAN_EXCEPTION (message, error);
156 return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
159 if (! _notmuch_message_frozen (message))
160 _notmuch_message_sync (message);
162 return NOTMUCH_STATUS_SUCCESS;
166 notmuch_message_remove_all_properties (notmuch_message_t *message, const char *key)
168 return _notmuch_message_remove_all_properties (message, key, false);
172 notmuch_message_remove_all_properties_with_prefix (notmuch_message_t *message, const char *prefix)
174 return _notmuch_message_remove_all_properties (message, prefix, true);
177 notmuch_message_properties_t *
178 notmuch_message_get_properties (notmuch_message_t *message, const char *key, notmuch_bool_t exact)
180 notmuch_string_map_t *map;
182 map = _notmuch_message_property_map (message);
183 return _notmuch_string_map_iterator_create (map, key, exact);
187 notmuch_message_properties_valid (notmuch_message_properties_t *properties)
189 return _notmuch_string_map_iterator_valid (properties);
193 notmuch_message_properties_move_to_next (notmuch_message_properties_t *properties)
195 return _notmuch_string_map_iterator_move_to_next (properties);
199 notmuch_message_properties_key (notmuch_message_properties_t *properties)
201 return _notmuch_string_map_iterator_key (properties);
205 notmuch_message_properties_value (notmuch_message_properties_t *properties)
207 return _notmuch_string_map_iterator_value (properties);
211 notmuch_message_properties_destroy (notmuch_message_properties_t *properties)
213 _notmuch_string_map_iterator_destroy (properties);