From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id AOBcIrJv318KJgAA0tVLHw (envelope-from ) for ; Sun, 20 Dec 2020 15:37:22 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1 with LMTPS id eGYIHrJv31+xPgAAbx9fmQ (envelope-from ) for ; Sun, 20 Dec 2020 15:37:22 +0000 Received: from mail.notmuchmail.org (nmbug.tethera.net [IPv6:2607:5300:201:3100::1657]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (2048 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 5A2A094042C for ; Sun, 20 Dec 2020 15:37:19 +0000 (UTC) Received: from nmbug.tethera.net (localhost [127.0.0.1]) by mail.notmuchmail.org (Postfix) with ESMTP id 417FF29BF6; Sun, 20 Dec 2020 10:37:09 -0500 (EST) Received: from lahtoruutu.iki.fi (unknown [IPv6:2a0b:5c81:1c1::37]) by mail.notmuchmail.org (Postfix) with ESMTPS id 475A32853C for ; Sun, 20 Dec 2020 10:37:06 -0500 (EST) Received: from guru.guru-group.fi (unknown [IPv6:2a02:2380:1:9:5054:ff:feb7:a4bc]) (using TLSv1.2 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: too) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 849141B00145; Sun, 20 Dec 2020 17:36:53 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1608478613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=kEs/00PWvSxw+s4Xx333AE0AnsRW5gDzDLnNoG9FRuM=; b=oM6BJtFdyd3Qf1vNtNWkyZX3YiZrp/+KTq3HA0KqdMSQinvwwr9FxCbYO/rMr6AXEfR/M8 FQ3RkHiPYfp66B/ZFc+RMChtPczH3eb9T/D0uS15KOJfqGDU4iIyTuG6hCZxh53y7NHxmb E5Djir727u6hhH/aQdyaCrHHpmuljsIVp9hMCvQj8ru4GQJ1i3p5fXGjYhXFzjKyDBJ7yY j0DDN2NdC0fFPjjPtBOgBCN51gU8xFTjLdGWTWGHP5kqKaUk5GMbGk+VoiiEEKhWV1utcD M85dfgx8gKGikXQcL+M0pNLPBRIk8icESX/jHryu/CUobzno2Ve28Tv7Rifs0Q== From: Tomi Ollila To: David Bremner , notmuch@notmuchmail.org Cc: David Bremner Subject: Re: [PATCH 3/6] lib: factor out prefix related code to its own file In-Reply-To: <20201220121024.1122362-4-david@tethera.net> References: <20201220121024.1122362-1-david@tethera.net> <20201220121024.1122362-4-david@tethera.net> User-Agent: Notmuch/0.31.2+29~gf517255 (https://notmuchmail.org) Emacs/27.1 X-Face: HhBM'cA~ MIME-Version: 1.0 ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1608478613; a=rsa-sha256; cv=none; b=HBdqWmQcTmohL40UzgSIH0Wh1TcinOy9rBJxxC7R/fkV25PgQnQ4+F/p1hJhiyU3FYFbr/ uDgOnaWTIUckQMMo7gqOkM2sxkc1HEhj4/ZSHPDDRdmMklIm3pj88M4ONO+TBcsI0KvGY0 PaO17+/Ah5j/nkjDszAaz7ugj2d7u0Gwy4gNfdDMXHqSitKFYJyz8fUARwvZl3y5dwtdks zUWkNswx9SvOJ2g+2zs7pgjCGaqIsJMhIGpxYnrWuEKyCq5PZ2XJTZkfdEPT9N8xjbgud2 /gYutdbOKQ1y8WnaeHE5Wn1wZd+kS71MAKxsFbsEEurObCa1cJMt60m8jtOjgQ== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=too smtp.mailfrom=tomi.ollila@iki.fi ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1608478613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=kEs/00PWvSxw+s4Xx333AE0AnsRW5gDzDLnNoG9FRuM=; b=jYA81l4C2wxDv0PPljR0DC/XvF6EWCpQLFv56cedbSyCJsKJEVmC7L0VY1sqMjNfjG4IJc lfL1mwiFyr9TUJ+q/wopqK7LKk1GSzjZtEvcuhGXxS4xnv/9fNA57H8swQXNGqvOdEz745 uaPrFFQTxhR4ldMPxm2JbfJ2UMnQBt8kcddDmY4k1M9mEz9UCMrlYSfsWj//d3lse95vEA 6Q15fIdw9+2Gmm+iD9flDPSeag/hC4vKJOtCrX+JZmtOW9CYxL7np+IfnDRgEdQzySIMAO ReOrrxM3hR+1Vy8sgcGRDzWA3/j4qCPdahgligrMD8TiGTsfPqfgUg8CODm53g== Message-ID-Hash: YY5TE5GXBNKJADJBYLST4U6C76SZHBDY X-Message-ID-Hash: YY5TE5GXBNKJADJBYLST4U6C76SZHBDY X-MailFrom: tomi.ollila@iki.fi X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-notmuch.notmuchmail.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.1 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: 2.66 Authentication-Results: aspmx1.migadu.com; dkim=fail (body hash did not verify) header.d=iki.fi header.s=lahtoruutu header.b=oM6BJtFd; arc=reject (signature check failed: fail, {[1] = sig:iki.fi:reject}); dmarc=none; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 2607:5300:201:3100::1657 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Migadu-Queue-Id: 5A2A094042C X-Spam-Score: 2.66 X-Migadu-Scanner: scn0.migadu.com X-TUID: NuciWFXNGONS On Sun, Dec 20 2020, David Bremner wrote: > Reduce the size of database.cc, and limit the scope of prefix_table, > make sure it's accessed via a well-defined internal API. > --- > lib/Makefile.local | 4 +- > lib/database-private.h | 7 ++ > lib/database.cc | 203 ++------------------------------------- > lib/prefix.cc | 210 +++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 229 insertions(+), 195 deletions(-) > create mode 100644 lib/prefix.cc > > diff --git a/lib/Makefile.local b/lib/Makefile.local > index 04418fa8..3aa9e80f 100644 > --- a/lib/Makefile.local > +++ b/lib/Makefile.local > @@ -60,7 +60,9 @@ libnotmuch_cxx_srcs = \ > $(dir)/regexp-fields.cc \ > $(dir)/thread.cc \ > $(dir)/thread-fp.cc \ > - $(dir)/features.cc > + $(dir)/features.cc \ > + $(dir)/prefix.cc > + Good stuff! is this extra line above intentional ? (otherwise I did not find anything else, but I may have got tired looking through the series ;/) Tomi > > libnotmuch_modules := $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o) > > diff --git a/lib/database-private.h b/lib/database-private.h > index 2d220811..c9bc712b 100644 > --- a/lib/database-private.h > +++ b/lib/database-private.h > @@ -277,4 +277,11 @@ _notmuch_database_parse_features (const void *ctx, const char *features, unsigne > char * > _notmuch_database_print_features (const void *ctx, unsigned int features); > > +/* prefix.cc */ > +notmuch_status_t > +_notmuch_database_setup_standard_query_fields (notmuch_database_t *notmuch); > + > +notmuch_status_t > +_notmuch_database_setup_user_query_fields (notmuch_database_t *notmuch); > + > #endif > diff --git a/lib/database.cc b/lib/database.cc > index 4a477bd7..defa3062 100644 > --- a/lib/database.cc > +++ b/lib/database.cc > @@ -263,80 +263,6 @@ _notmuch_database_mode (notmuch_database_t *notmuch) > * same thread. > */ > > -/* With these prefix values we follow the conventions published here: > - * > - * https://xapian.org/docs/omega/termprefixes.html > - * > - * as much as makes sense. Note that I took some liberty in matching > - * the reserved prefix values to notmuch concepts, (for example, 'G' > - * is documented as "newsGroup (or similar entity - e.g. a web forum > - * name)", for which I think the thread is the closest analogue in > - * notmuch. This in spite of the fact that we will eventually be > - * storing mailing-list messages where 'G' for "mailing list name" > - * might be even a closer analogue. I'm treating the single-character > - * prefixes preferentially for core notmuch concepts (which will be > - * nearly universal to all mail messages). > - */ > - > -static const > -prefix_t prefix_table[] = { > - /* name term prefix flags */ > - { "type", "T", NOTMUCH_FIELD_NO_FLAGS }, > - { "reference", "XREFERENCE", NOTMUCH_FIELD_NO_FLAGS }, > - { "replyto", "XREPLYTO", NOTMUCH_FIELD_NO_FLAGS }, > - { "directory", "XDIRECTORY", NOTMUCH_FIELD_NO_FLAGS }, > - { "file-direntry", "XFDIRENTRY", NOTMUCH_FIELD_NO_FLAGS }, > - { "directory-direntry", "XDDIRENTRY", NOTMUCH_FIELD_NO_FLAGS }, > - { "body", "", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROBABILISTIC }, > - { "thread", "G", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "tag", "K", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "is", "K", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "id", "Q", NOTMUCH_FIELD_EXTERNAL }, > - { "mid", "Q", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "path", "P", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL }, > - /* > - * Unconditionally add ':' to reduce potential ambiguity with > - * overlapping prefixes and/or terms that start with capital > - * letters. See Xapian document termprefixes.html for related > - * discussion. > - */ > - { "folder", "XFOLDER:", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "date", NULL, NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "query", NULL, NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROCESSOR }, > - { "from", "XFROM", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROBABILISTIC | > - NOTMUCH_FIELD_PROCESSOR }, > - { "to", "XTO", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROBABILISTIC }, > - { "attachment", "XATTACHMENT", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROBABILISTIC }, > - { "mimetype", "XMIMETYPE", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROBABILISTIC }, > - { "subject", "XSUBJECT", NOTMUCH_FIELD_EXTERNAL | > - NOTMUCH_FIELD_PROBABILISTIC | > - NOTMUCH_FIELD_PROCESSOR }, > -}; > - > -static void > -_setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) > -{ > - if (prefix->prefix) > - notmuch->query_parser->add_prefix ("", prefix->prefix); > - if (prefix->flags & NOTMUCH_FIELD_PROBABILISTIC) > - notmuch->query_parser->add_prefix (prefix->name, prefix->prefix); > - else > - notmuch->query_parser->add_boolean_prefix (prefix->name, prefix->prefix); > -} > > notmuch_string_map_iterator_t * > _notmuch_database_user_headers (notmuch_database_t *notmuch) > @@ -344,118 +270,6 @@ _notmuch_database_user_headers (notmuch_database_t *notmuch) > return _notmuch_string_map_iterator_create (notmuch->user_header, "", false); > } > > -const char * > -_user_prefix (void *ctx, const char *name) > -{ > - return talloc_asprintf (ctx, "XU%s:", name); > -} > - > -static notmuch_status_t > -_setup_user_query_fields (notmuch_database_t *notmuch) > -{ > - notmuch_config_list_t *list; > - notmuch_status_t status; > - > - notmuch->user_prefix = _notmuch_string_map_create (notmuch); > - if (notmuch->user_prefix == NULL) > - return NOTMUCH_STATUS_OUT_OF_MEMORY; > - > - notmuch->user_header = _notmuch_string_map_create (notmuch); > - if (notmuch->user_header == NULL) > - return NOTMUCH_STATUS_OUT_OF_MEMORY; > - > - status = notmuch_database_get_config_list (notmuch, CONFIG_HEADER_PREFIX, &list); > - if (status) > - return status; > - > - for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) { > - > - prefix_t query_field; > - > - const char *key = notmuch_config_list_key (list) > - + sizeof (CONFIG_HEADER_PREFIX) - 1; > - > - _notmuch_string_map_append (notmuch->user_prefix, > - key, > - _user_prefix (notmuch, key)); > - > - _notmuch_string_map_append (notmuch->user_header, > - key, > - notmuch_config_list_value (list)); > - > - query_field.name = talloc_strdup (notmuch, key); > - query_field.prefix = _user_prefix (notmuch, key); > - query_field.flags = NOTMUCH_FIELD_PROBABILISTIC > - | NOTMUCH_FIELD_EXTERNAL; > - > - _setup_query_field_default (&query_field, notmuch); > - } > - > - notmuch_config_list_destroy (list); > - > - return NOTMUCH_STATUS_SUCCESS; > -} > - > -static void > -_setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch) > -{ > - if (prefix->flags & NOTMUCH_FIELD_PROCESSOR) { > - Xapian::FieldProcessor *fp; > - > - if (STRNCMP_LITERAL (prefix->name, "date") == 0) > - fp = (new DateFieldProcessor(NOTMUCH_VALUE_TIMESTAMP))->release (); > - else if (STRNCMP_LITERAL(prefix->name, "query") == 0) > - fp = (new QueryFieldProcessor (*notmuch->query_parser, notmuch))->release (); > - else if (STRNCMP_LITERAL (prefix->name, "thread") == 0) > - fp = (new ThreadFieldProcessor (*notmuch->query_parser, notmuch))->release (); > - else > - fp = (new RegexpFieldProcessor (prefix->name, prefix->flags, > - *notmuch->query_parser, notmuch))->release (); > - > - /* we treat all field-processor fields as boolean in order to get the raw input */ > - if (prefix->prefix) > - notmuch->query_parser->add_prefix ("", prefix->prefix); > - notmuch->query_parser->add_boolean_prefix (prefix->name, fp); > - } else { > - _setup_query_field_default (prefix, notmuch); > - } > -} > - > -const char * > -_find_prefix (const char *name) > -{ > - unsigned int i; > - > - for (i = 0; i < ARRAY_SIZE (prefix_table); i++) { > - if (strcmp (name, prefix_table[i].name) == 0) > - return prefix_table[i].prefix; > - } > - > - INTERNAL_ERROR ("No prefix exists for '%s'\n", name); > - > - return ""; > -} > - > -/* Like find prefix, but include the possibility of user defined > - * prefixes specific to this database */ > - > -const char * > -_notmuch_database_prefix (notmuch_database_t *notmuch, const char *name) > -{ > - unsigned int i; > - > - /*XXX TODO: reduce code duplication */ > - for (i = 0; i < ARRAY_SIZE (prefix_table); i++) { > - if (strcmp (name, prefix_table[i].name) == 0) > - return prefix_table[i].prefix; > - } > - > - if (notmuch->user_prefix) > - return _notmuch_string_map_get (notmuch->user_prefix, name); > - > - return NULL; > -} > - > const char * > notmuch_status_to_string (notmuch_status_t status) > { > @@ -898,7 +712,7 @@ notmuch_database_open_verbose (const char *path, > > /* Check features. */ > incompat_features = NULL; > - notmuch->features = _parse_features ( > + notmuch->features = _notmuch_database_parse_features ( > local, notmuch->xapian_db->get_metadata ("features").c_str (), > version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r', > &incompat_features); > @@ -952,13 +766,14 @@ notmuch_database_open_verbose (const char *path, > notmuch->query_parser->add_rangeprocessor (notmuch->date_range_processor); > notmuch->query_parser->add_rangeprocessor (notmuch->last_mod_range_processor); > > - for (i = 0; i < ARRAY_SIZE (prefix_table); i++) { > - const prefix_t *prefix = &prefix_table[i]; > - if (prefix->flags & NOTMUCH_FIELD_EXTERNAL) { > - _setup_query_field (prefix, notmuch); > - } > - } > - status = _setup_user_query_fields (notmuch); > + status = _notmuch_database_setup_standard_query_fields (notmuch); > + if (status) > + goto DONE; > + > + status = _notmuch_database_setup_user_query_fields (notmuch); > + if (status) > + goto DONE; > + > } catch (const Xapian::Error &error) { > IGNORE_RESULT (asprintf (&message, "A Xapian exception occurred opening database: %s\n", > error.get_msg ().c_str ())); > diff --git a/lib/prefix.cc b/lib/prefix.cc > new file mode 100644 > index 00000000..dd7b193d > --- /dev/null > +++ b/lib/prefix.cc > @@ -0,0 +1,210 @@ > +#include "database-private.h" > +#include "query-fp.h" > +#include "thread-fp.h" > +#include "regexp-fields.h" > +#include "parse-time-vrp.h" > + > +typedef struct { > + const char *name; > + const char *prefix; > + notmuch_field_flag_t flags; > +} prefix_t; > + > +/* With these prefix values we follow the conventions published here: > + * > + * https://xapian.org/docs/omega/termprefixes.html > + * > + * as much as makes sense. Note that I took some liberty in matching > + * the reserved prefix values to notmuch concepts, (for example, 'G' > + * is documented as "newsGroup (or similar entity - e.g. a web forum > + * name)", for which I think the thread is the closest analogue in > + * notmuch. This in spite of the fact that we will eventually be > + * storing mailing-list messages where 'G' for "mailing list name" > + * might be even a closer analogue. I'm treating the single-character > + * prefixes preferentially for core notmuch concepts (which will be > + * nearly universal to all mail messages). > + */ > + > +static const > +prefix_t prefix_table[] = { > + /* name term prefix flags */ > + { "type", "T", NOTMUCH_FIELD_NO_FLAGS }, > + { "reference", "XREFERENCE", NOTMUCH_FIELD_NO_FLAGS }, > + { "replyto", "XREPLYTO", NOTMUCH_FIELD_NO_FLAGS }, > + { "directory", "XDIRECTORY", NOTMUCH_FIELD_NO_FLAGS }, > + { "file-direntry", "XFDIRENTRY", NOTMUCH_FIELD_NO_FLAGS }, > + { "directory-direntry", "XDDIRENTRY", NOTMUCH_FIELD_NO_FLAGS }, > + { "body", "", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROBABILISTIC }, > + { "thread", "G", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "tag", "K", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "is", "K", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "id", "Q", NOTMUCH_FIELD_EXTERNAL }, > + { "mid", "Q", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "path", "P", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL }, > + /* > + * Unconditionally add ':' to reduce potential ambiguity with > + * overlapping prefixes and/or terms that start with capital > + * letters. See Xapian document termprefixes.html for related > + * discussion. > + */ > + { "folder", "XFOLDER:", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "date", NULL, NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "query", NULL, NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROCESSOR }, > + { "from", "XFROM", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROBABILISTIC | > + NOTMUCH_FIELD_PROCESSOR }, > + { "to", "XTO", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROBABILISTIC }, > + { "attachment", "XATTACHMENT", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROBABILISTIC }, > + { "mimetype", "XMIMETYPE", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROBABILISTIC }, > + { "subject", "XSUBJECT", NOTMUCH_FIELD_EXTERNAL | > + NOTMUCH_FIELD_PROBABILISTIC | > + NOTMUCH_FIELD_PROCESSOR }, > +}; > + > +static const char * > +_user_prefix (void *ctx, const char *name) > +{ > + return talloc_asprintf (ctx, "XU%s:", name); > +} > + > +const char * > +_find_prefix (const char *name) > +{ > + unsigned int i; > + > + for (i = 0; i < ARRAY_SIZE (prefix_table); i++) { > + if (strcmp (name, prefix_table[i].name) == 0) > + return prefix_table[i].prefix; > + } > + > + INTERNAL_ERROR ("No prefix exists for '%s'\n", name); > + > + return ""; > +} > + > +/* Like find prefix, but include the possibility of user defined > + * prefixes specific to this database */ > + > +const char * > +_notmuch_database_prefix (notmuch_database_t *notmuch, const char *name) > +{ > + unsigned int i; > + > + /*XXX TODO: reduce code duplication */ > + for (i = 0; i < ARRAY_SIZE (prefix_table); i++) { > + if (strcmp (name, prefix_table[i].name) == 0) > + return prefix_table[i].prefix; > + } > + > + if (notmuch->user_prefix) > + return _notmuch_string_map_get (notmuch->user_prefix, name); > + > + return NULL; > +} > + > +static void > +_setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) > +{ > + if (prefix->prefix) > + notmuch->query_parser->add_prefix ("", prefix->prefix); > + if (prefix->flags & NOTMUCH_FIELD_PROBABILISTIC) > + notmuch->query_parser->add_prefix (prefix->name, prefix->prefix); > + else > + notmuch->query_parser->add_boolean_prefix (prefix->name, prefix->prefix); > +} > + > +static void > +_setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch) > +{ > + if (prefix->flags & NOTMUCH_FIELD_PROCESSOR) { > + Xapian::FieldProcessor *fp; > + > + if (STRNCMP_LITERAL (prefix->name, "date") == 0) > + fp = (new DateFieldProcessor(NOTMUCH_VALUE_TIMESTAMP))->release (); > + else if (STRNCMP_LITERAL(prefix->name, "query") == 0) > + fp = (new QueryFieldProcessor (*notmuch->query_parser, notmuch))->release (); > + else if (STRNCMP_LITERAL (prefix->name, "thread") == 0) > + fp = (new ThreadFieldProcessor (*notmuch->query_parser, notmuch))->release (); > + else > + fp = (new RegexpFieldProcessor (prefix->name, prefix->flags, > + *notmuch->query_parser, notmuch))->release (); > + > + /* we treat all field-processor fields as boolean in order to get the raw input */ > + if (prefix->prefix) > + notmuch->query_parser->add_prefix ("", prefix->prefix); > + notmuch->query_parser->add_boolean_prefix (prefix->name, fp); > + } else { > + _setup_query_field_default (prefix, notmuch); > + } > +} > + > +notmuch_status_t > +_notmuch_database_setup_standard_query_fields (notmuch_database_t *notmuch) > +{ > + for (unsigned int i = 0; i < ARRAY_SIZE (prefix_table); i++) { > + const prefix_t *prefix = &prefix_table[i]; > + if (prefix->flags & NOTMUCH_FIELD_EXTERNAL) { > + _setup_query_field (prefix, notmuch); > + } > + } > + return NOTMUCH_STATUS_SUCCESS; > +} > + > +notmuch_status_t > +_notmuch_database_setup_user_query_fields (notmuch_database_t *notmuch) > +{ > + notmuch_config_list_t *list; > + notmuch_status_t status; > + > + notmuch->user_prefix = _notmuch_string_map_create (notmuch); > + if (notmuch->user_prefix == NULL) > + return NOTMUCH_STATUS_OUT_OF_MEMORY; > + > + notmuch->user_header = _notmuch_string_map_create (notmuch); > + if (notmuch->user_header == NULL) > + return NOTMUCH_STATUS_OUT_OF_MEMORY; > + > + status = notmuch_database_get_config_list (notmuch, CONFIG_HEADER_PREFIX, &list); > + if (status) > + return status; > + > + for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) { > + > + prefix_t query_field; > + > + const char *key = notmuch_config_list_key (list) > + + sizeof (CONFIG_HEADER_PREFIX) - 1; > + > + _notmuch_string_map_append (notmuch->user_prefix, > + key, > + _user_prefix (notmuch, key)); > + > + _notmuch_string_map_append (notmuch->user_header, > + key, > + notmuch_config_list_value (list)); > + > + query_field.name = talloc_strdup (notmuch, key); > + query_field.prefix = _user_prefix (notmuch, key); > + query_field.flags = NOTMUCH_FIELD_PROBABILISTIC > + | NOTMUCH_FIELD_EXTERNAL; > + > + _setup_query_field_default (&query_field, notmuch); > + } > + > + notmuch_config_list_destroy (list); > + > + return NOTMUCH_STATUS_SUCCESS; > +} > -- > 2.29.2 > _______________________________________________ > notmuch mailing list -- notmuch@notmuchmail.org > To unsubscribe send an email to notmuch-leave@notmuchmail.org