From 27c7aa40cdd7eb1c96c38b12d5161d34d140dac6 Mon Sep 17 00:00:00 2001 From: "Steffen (Daode) Nurpmeso" Date: Fri, 19 Aug 2016 16:09:54 +0200 Subject: [PATCH] Move struct ignoretab stuff to new ignoretab.c and rewrite.. Reduce the still fixed-size hashtable size, and place each member in a single continuous memory chunk. Add a yet simple object-based approach, and allow memory to be placed in auto-reclaimed memory. --- cmd2.c | 291 ---------------------------------------- head.c | 43 ------ ignoretab.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nail.h | 16 ++- nailfuns.h | 73 ++++++---- 5 files changed, 493 insertions(+), 366 deletions(-) create mode 100644 ignoretab.c diff --git a/cmd2.c b/cmd2.c index c39d8416..6cf9f67e 100644 --- a/cmd2.c +++ b/cmd2.c @@ -55,19 +55,6 @@ static char * snarf(char *linebuf, bool_t *flag, bool_t usembox); /* Delete the indicated messages. Set dot to some nice place afterwards */ static int delm(int *msgvec); -static int ignore1(char **list, struct ignoretab *tab, char const *which); - -/* Print out all currently retained fields */ -static int igshow(struct ignoretab *tab, char const *which); - -/* Compare two names for sorting ignored field list */ -static int igcomp(void const *l, void const *r); - -/* */ -static int _unignore(char **list, struct ignoretab *tab, char const *which); -static void __unign_all(struct ignoretab *tab); -static void __unign_one(struct ignoretab *tab, char const *name); - static int save1(char *str, int domark, char const *cmd, struct ignoretab *ignoret, int convert, int sender_record, int domove) @@ -309,146 +296,6 @@ delm(int *msgvec) return rv; } -static int -ignore1(char **list, struct ignoretab *tab, char const *which) -{ - int h; - struct ignored *igp; - char **ap; - NYD_ENTER; - - if (*list == NULL) { - h = igshow(tab, which); - goto jleave; - } - - for (ap = list; *ap != 0; ++ap) { - char *field; - size_t sz; - - sz = strlen(*ap) +1; - field = ac_alloc(sz); - i_strcpy(field, *ap, sz); - if (member(field, tab)) - goto jnext; - - h = hash(field); - igp = scalloc(1, sizeof *igp); - sz = strlen(field) +1; - igp->i_field = smalloc(sz); - memcpy(igp->i_field, field, sz); - igp->i_link = tab->i_head[h]; - tab->i_head[h] = igp; - ++tab->i_count; -jnext: - ac_free(field); - } - h = 0; -jleave: - NYD_LEAVE; - return h; -} - -static int -igshow(struct ignoretab *tab, char const *which) -{ - int h; - struct ignored *igp; - char **ap, **ring; - NYD_ENTER; - - if (tab->i_count == 0) { - printf(_("No fields currently being %s.\n"), which); - goto jleave; - } - - ring = salloc((tab->i_count + 1) * sizeof *ring); - ap = ring; - for (h = 0; h < HSHSIZE; ++h) - for (igp = tab->i_head[h]; igp != 0; igp = igp->i_link) - *ap++ = igp->i_field; - *ap = 0; - - qsort(ring, tab->i_count, sizeof *ring, igcomp); - - for (ap = ring; *ap != NULL; ++ap) - printf("%s\n", *ap); -jleave: - NYD_LEAVE; - return 0; -} - -static int -igcomp(void const *l, void const *r) -{ - int rv; - NYD_ENTER; - - rv = strcmp(*(char**)UNCONST(l), *(char**)UNCONST(r)); - NYD_LEAVE; - return rv; -} - -static int -_unignore(char **list, struct ignoretab *tab, char const *which) -{ - char *field; - NYD_ENTER; - - if (tab->i_count == 0) - printf(_("No fields currently being %s.\n"), which); - else - while ((field = *list++) != NULL) - if (field[0] == '*' && field[1] == '\0') { - __unign_all(tab); - break; - } else - __unign_one(tab, field); - NYD_LEAVE; - return 0; -} - -static void -__unign_all(struct ignoretab *tab) -{ - size_t i; - struct ignored *n, *x; - NYD_ENTER; - - for (i = 0; i < NELEM(tab->i_head); ++i) - for (n = tab->i_head[i]; n != NULL; n = x) { - x = n->i_link; - free(n->i_field); - free(n); - } - memset(tab, 0, sizeof *tab); - NYD_LEAVE; -} - -static void -__unign_one(struct ignoretab *tab, char const *name) -{ - struct ignored *ip, *iq; - int h; - NYD_ENTER; - - h = hash(name); - for (iq = NULL, ip = tab->i_head[h]; ip != NULL; ip = ip->i_link) { - if (!asccasecmp(ip->i_field, name)) { - free(ip->i_field); - if (iq != NULL) - iq->i_link = ip->i_link; - else - tab->i_head[h] = ip->i_link; - free(ip); - --tab->i_count; - break; - } - iq = ip; - } - NYD_LEAVE; -} - FL int c_next(void *v) { @@ -722,142 +569,4 @@ c_undelete(void *v) return 0; } -FL int -c_retfield(void *v) -{ - char **list = v; - int rv; - NYD_ENTER; - - rv = ignore1(list, ignore + 1, "retained"); - NYD_LEAVE; - return rv; -} - -FL int -c_igfield(void *v) -{ - char **list = v; - int rv; - NYD_ENTER; - - rv = ignore1(list, ignore, "ignored"); - NYD_LEAVE; - return rv; -} - -FL int -c_saveretfield(void *v) -{ - char **list = v; - int rv; - NYD_ENTER; - - rv = ignore1(list, saveignore + 1, "retained"); - NYD_LEAVE; - return rv; -} - -FL int -c_saveigfield(void *v) -{ - char **list = v; - int rv; - NYD_ENTER; - - rv = ignore1(list, saveignore, "ignored"); - NYD_LEAVE; - return rv; -} - -FL int -c_fwdretfield(void *v) -{ - char **list = v; - int rv; - NYD_ENTER; - - rv = ignore1(list, fwdignore + 1, "retained"); - NYD_LEAVE; - return rv; -} - -FL int -c_fwdigfield(void *v) -{ - char **list = v; - int rv; - NYD_ENTER; - - rv = ignore1(list, fwdignore, "ignored"); - NYD_LEAVE; - return rv; -} - -FL int -c_unignore(void *v) -{ - int rv; - NYD_ENTER; - - rv = _unignore((char**)v, ignore, "ignored"); - NYD_LEAVE; - return rv; -} - -FL int -c_unretain(void *v) -{ - int rv; - NYD_ENTER; - - rv = _unignore((char**)v, ignore + 1, "retained"); - NYD_LEAVE; - return rv; -} - -FL int -c_unsaveignore(void *v) -{ - int rv; - NYD_ENTER; - - rv = _unignore((char**)v, saveignore, "ignored"); - NYD_LEAVE; - return rv; -} - -FL int -c_unsaveretain(void *v) -{ - int rv; - NYD_ENTER; - - rv = _unignore((char**)v, saveignore + 1, "retained"); - NYD_LEAVE; - return rv; -} - -FL int -c_unfwdignore(void *v) -{ - int rv; - NYD_ENTER; - - rv = _unignore((char**)v, fwdignore, "ignored"); - NYD_LEAVE; - return rv; -} - -FL int -c_unfwdretain(void *v) -{ - int rv; - NYD_ENTER; - - rv = _unignore((char**)v, fwdignore + 1, "retained"); - NYD_LEAVE; - return rv; -} - /* s-it-mode */ diff --git a/head.c b/head.c index e603f823..3c745479 100644 --- a/head.c +++ b/head.c @@ -1658,49 +1658,6 @@ msgidcmp(char const *s1, char const *s2) return c1 - c2; } -FL int -is_ign(char const *field, size_t fieldlen, struct ignoretab igta[2]) -{ - char *realfld; - int rv; - NYD_ENTER; - - rv = 0; - if (igta == NULL) - goto jleave; - rv = 1; - if (igta == allignore) - goto jleave; - - /* Lowercase it so that "Status" and "status" will hash to the same place */ - realfld = ac_alloc(fieldlen +1); - i_strcpy(realfld, field, fieldlen +1); - if (igta[1].i_count > 0) - rv = !member(realfld, igta + 1); - else - rv = member(realfld, igta); - ac_free(realfld); -jleave: - NYD_LEAVE; - return rv; -} - -FL int -member(char const *realfield, struct ignoretab *table) -{ - struct ignored *igp; - int rv = 0; - NYD_ENTER; - - for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link) - if (*igp->i_field == *realfield && !strcmp(igp->i_field, realfield)) { - rv = 1; - break; - } - NYD_LEAVE; - return rv; -} - FL char const * fakefrom(struct message *mp) { diff --git a/ignoretab.c b/ignoretab.c new file mode 100644 index 00000000..b813689f --- /dev/null +++ b/ignoretab.c @@ -0,0 +1,436 @@ +/*@ S-nail - a mail user agent derived from Berkeley Mail. + *@ `ignore' and `retain' lists of all sort. + *@ XXX Should these be in nam_a_grp.c?! + * + * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany. + * Copyright (c) 2012 - 2016 Steffen (Daode) Nurpmeso . + */ +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#undef n_FILE +#define n_FILE ignoretab + +#ifndef HAVE_AMALGAMATION +# include "nail.h" +#endif + +/* Add a list of fields to be ignored or retained */ +static bool_t a_ignoretab_insert(char const **list, struct ignoretab *itp, + bool_t ignorret); + +static void a_ignoretab__show(struct ignoretab *itp, bool_t ignorret); +static int a_ignoretab__cmp(void const *l, void const *r); + +/* Delete a list of fields from an ignored or retained list) */ +static bool_t a_ignoretab_del(char const **list, struct ignoretab *itp, + bool_t ignorret); + +static void a_ignoretab__delall(struct ignoretab *itp); +static bool_t a_ignoretab__del(struct ignoretab *itp, char const *name); + +static bool_t +a_ignoretab_insert(char const **list, struct ignoretab *itp, bool_t ignorret){ + char const **ap; + bool_t rv; + NYD2_ENTER; + + rv = TRU1; + + if(*list == NULL) + a_ignoretab__show(itp, ignorret); + else{ + for(ap = list; *ap != 0; ++ap) + switch(n_ignoretab_insert_cp(itp, *ap)){ + case FAL0: + n_err(_("Invalid field name cannot be %s: %s\n"), + (ignorret ? _("ignored") : _("retained")), *ap); + rv = FAL0; + break; + case TRUM1: + if(options & OPT_D_V) + n_err(_("Field already %s: %s\n"), + (ignorret ? _("ignored") : _("retained")), *ap); + /* FALLTHRU */ + case TRU1: + break; + } + } + NYD2_LEAVE; + return rv; +} + +static void +a_ignoretab__show(struct ignoretab *itp, bool_t ignorret){ + struct n_ignoretab_field *itfp; + size_t i, sw; + char const **ap, **ring; + NYD2_ENTER; + + if(itp->it_count == 0){ + printf(_("No fields currently being %s\n"), + (ignorret ? _("ignored") : _("retained"))); + goto jleave; + } + + ring = salloc((itp->it_count +1) * sizeof *ring); + for(ap = ring, i = 0; i < NELEM(itp->it_head); ++i) + for(itfp = itp->it_head[i]; itfp != NULL; itfp = itfp->itf_next) + *ap++ = itfp->itf_field; + *ap = NULL; + + qsort(ring, itp->it_count, sizeof *ring, &a_ignoretab__cmp); + + for(sw = scrnwidth, i = 0, ap = ring; *ap != NULL; ++ap){ + /* These fields are all ASCII */ + size_t len; + char const *pref; + + pref = " "; + len = strlen(*ap) + 2; + if(UICMP(z, len, >=, sw - i)){ + putchar('\n'); + i = 2; + }else if(i == 0) + pref = ""; + i += len; + printf("%s%s", pref, *ap); + } + if(i > 0){ + putchar('\n'); + fflush(stdout); + } +jleave: + NYD2_LEAVE; +} + +static int +a_ignoretab__cmp(void const *l, void const *r){ + int rv; + + rv = asccasecmp(*(char const * const *)l, *(char const * const *)r); + return rv; +} + +static bool_t +a_ignoretab_del(char const **list, struct ignoretab *itp, bool_t ignorret){ + char const *cp; + bool_t rv; + NYD2_ENTER; + + rv = TRU1; + + if(itp->it_count == 0) + printf(_("No fields currently being %s\n"), + (ignorret ? _("ignored") : _("retained"))); + else + while((cp = *list++) != NULL) + if(cp[0] == '*' && cp[1] == '\0') + a_ignoretab__delall(itp); + else if(!a_ignoretab__del(itp, cp)){ + n_err(_("Field not %s: %s\n"), + (ignorret ? _("ignored") : _("retained")), cp); + rv = FAL0; + } + NYD2_LEAVE; + return rv; +} + +static void +a_ignoretab__delall(struct ignoretab *itp){ + size_t i; + struct n_ignoretab_field *itfp, *x; + bool_t isauto; + NYD2_ENTER; + + if(!(isauto = itp->it_auto)) + for(i = 0; i < NELEM(itp->it_head); ++i) + for(itfp = itp->it_head[i]; itfp != NULL; itfp = x){ + x = itfp->itf_next; + free(itfp); + } + + memset(itp, 0, sizeof *itp); + itp->it_auto = isauto; + NYD2_LEAVE; +} + +static bool_t +a_ignoretab__del(struct ignoretab *itp, char const *name){ + struct n_ignoretab_field **itfpp, *itfp; + ui32_t h; + NYD_ENTER; + + h = torek_ihashn(name, UIZ_MAX) % NELEM(itp->it_head); + + for(itfp = *(itfpp = &itp->it_head[h]); itfp != NULL; + itfpp = &itfp->itf_next, itfp = itfp->itf_next) + if(!asccasecmp(itfp->itf_field, name)){ + --itp->it_count; + *itfpp = itfp->itf_next; + if(!itp->it_auto) + free(itfp); + break; + } + NYD_LEAVE; + return (itfp != NULL); +} + +FL int +c_retfield(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_insert(v, &ignore[1], FAL0); + NYD_LEAVE; + return rv; +} + +FL int +c_igfield(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_insert(v, &ignore[0], TRU1); + NYD_LEAVE; + return rv; +} + +FL int +c_saveretfield(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_insert(v, &saveignore[1], FAL0); + NYD_LEAVE; + return rv; +} + +FL int +c_saveigfield(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_insert(v, &saveignore[0], TRU1); + NYD_LEAVE; + return rv; +} + +FL int +c_fwdretfield(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_insert(v, &fwdignore[1], FAL0); + NYD_LEAVE; + return rv; +} + +FL int +c_fwdigfield(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_insert(v, &fwdignore[0], TRU1); + NYD_LEAVE; + return rv; +} + +FL int +c_unignore(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_del(v, &ignore[0], TRU1); + NYD_LEAVE; + return rv; +} + +FL int +c_unretain(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_del(v, &ignore[1], FAL0); + NYD_LEAVE; + return rv; +} + +FL int +c_unsaveignore(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_del(v, &saveignore[0], TRU1); + NYD_LEAVE; + return rv; +} + +FL int +c_unsaveretain(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_del(v, &saveignore[1], FAL0); + NYD_LEAVE; + return rv; +} + +FL int +c_unfwdignore(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_del(v, &fwdignore[0], TRU1); + NYD_LEAVE; + return rv; +} + +FL int +c_unfwdretain(void *v){ + int rv; + NYD_ENTER; + + rv = !a_ignoretab_del(v, &fwdignore[1], FAL0); + NYD_LEAVE; + return rv; +} + +FL int +is_ign(char const *field, size_t fieldlen, struct ignoretab igta[2]){ + bool_t b; + int rv; + NYD_ENTER; + + rv = 0; + if(igta == NULL) + goto jleave; + rv = 1; + if(igta == allignore) + goto jleave; + + b = (igta[1].it_count > 0); + rv = n_ignoretab_lookup((b ? &igta[1] : &igta[0]), field, fieldlen); + if(b) + rv = !rv; +jleave: + NYD_LEAVE; + return rv; +} + +FL struct ignoretab * +n_ignoretab_creat(struct ignoretab *self, bool_t isauto){ + NYD_ENTER; + memset(self, 0, sizeof *self); + self->it_auto = isauto; + NYD_LEAVE; + return self; +} + +FL void +n_ignoretab_gut(struct ignoretab *self){ + NYD_ENTER; + if(!self->it_auto && self->it_count > 0) + a_ignoretab__delall(self); + NYD_LEAVE; +} + +FL bool_t +n_ignoretab_insert(struct ignoretab *self, char const *dat, size_t len){ + struct n_ignoretab_field *itfp; + ui32_t h; + bool_t rv; + NYD_ENTER; + + /* Detect length as necessary, check for valid fieldname */ + rv = FAL0; + if(len == UIZ_MAX){ + char c; + + for(len = 0; (c = dat[len]) != '\0'; ++len) + if(!fieldnamechar(c)) + goto jleave; + }else if(len == 0) + goto jleave; + else{ + char c; + size_t i; + + for(i = 0; i < len; ++i){ + c = dat[i]; + if(!fieldnamechar(c)) + goto jleave; + } + } + + rv = TRUM1; + if(n_ignoretab_lookup(self, dat, len)) + goto jleave; + else if(self->it_count == UI32_MAX){ + n_err(_("Hashtable size limit reached. Cannot insert: %.*s\n"), + (int)MIN(len, SI32_MAX), dat); + goto jleave; + } + + ++len; + /* C99 */{ + size_t i; + + i = sizeof(*itfp)-VFIELD_SIZEOF(struct n_ignoretab_field,itf_field) + len; + itfp = self->it_auto ? salloc(i) : smalloc(i); + } + --len; + memcpy(itfp->itf_field, dat, len); + itfp->itf_field[len] = '\0'; + h = torek_ihashn(dat, len) % NELEM(self->it_head); + itfp->itf_next = self->it_head[h]; + self->it_head[h] = itfp; + ++self->it_count; + rv = TRU1; +jleave: + NYD_LEAVE; + return rv; +} + +FL bool_t +n_ignoretab_lookup(struct ignoretab *self, char const *dat, size_t len){ + struct n_ignoretab_field *itfp; + NYD_ENTER; + + if(len == UIZ_MAX) + len = strlen(dat); + + for(itfp = self->it_head[torek_ihashn(dat, len) % NELEM(self->it_head)]; + itfp != NULL; itfp = itfp->itf_next) + if(!ascncasecmp(itfp->itf_field, dat, len)) + break; + NYD_LEAVE; + return (itfp != NULL); +} + +/* s-it-mode */ diff --git a/nail.h b/nail.h index d46f4250..1a791a18 100644 --- a/nail.h +++ b/nail.h @@ -2256,12 +2256,14 @@ struct sendbundle { }; /* Structure of the hash table of ignored header fields */ -struct ignoretab { - int i_count; /* Number of entries */ - struct ignored { - struct ignored *i_link; /* Next ignored field in bucket */ - char *i_field; /* This ignored field */ - } *i_head[HSHSIZE]; +struct ignoretab{ + ui32_t it_count; + bool_t it_auto; /* Stored in auto-reclaimed storage? */ + ui8_t it__dummy[3]; + struct n_ignoretab_field{ + struct n_ignoretab_field *itf_next; + char itf_field[VFIELD_SIZE(0)]; /* Header field */ + } *it_head[5 /* TODO make dynamic hashmap */]; }; /* For saving the current directory and later returning */ @@ -2331,8 +2333,8 @@ VL struct ignoretab ignore[2]; /* ignored and retained fields * 0 is ignore, 1 is retain */ VL struct ignoretab saveignore[2]; /* ignored and retained fields * on save to folder */ -VL struct ignoretab allignore[2]; /* special, ignore all headers */ VL struct ignoretab fwdignore[2]; /* fields to ignore for forwarding */ +#define allignore ((struct ignoretab*)-2) /* special, ignore all headers */ VL struct time_current time_current; /* time(3); send: mail1() XXXcarrier */ VL struct termios_state termios_state; /* getpassword(); see commands().. */ diff --git a/nailfuns.h b/nailfuns.h index 29555ebf..09773490 100644 --- a/nailfuns.h +++ b/nailfuns.h @@ -443,25 +443,6 @@ FL int c_deltype(void *v); /* Undelete the indicated messages */ FL int c_undelete(void *v); -/* Add the given header fields to the retained list. If no arguments, print - * the current list of retained fields */ -FL int c_retfield(void *v); - -/* Add the given header fields to the ignored list. If no arguments, print the - * current list of ignored fields */ -FL int c_igfield(void *v); - -FL int c_saveretfield(void *v); -FL int c_saveigfield(void *v); -FL int c_fwdretfield(void *v); -FL int c_fwdigfield(void *v); -FL int c_unignore(void *v); -FL int c_unretain(void *v); -FL int c_unsaveignore(void *v); -FL int c_unsaveretain(void *v); -FL int c_unfwdignore(void *v); -FL int c_unfwdretain(void *v); - /* * cmd3.c */ @@ -886,12 +867,6 @@ FL char * subject_re_trim(char *cp); FL int msgidcmp(char const *s1, char const *s2); -/* See if the given header field is supposed to be ignored */ -FL int is_ign(char const *field, size_t fieldlen, - struct ignoretab igta[2]); - -FL int member(char const *realfield, struct ignoretab *table); - /* Fake Sender for From_ lines if missing, e. g. with POP3 */ FL char const * fakefrom(struct message *mp); @@ -930,6 +905,54 @@ FL int grab_headers(struct header *hp, enum gfield gflags, FL bool_t header_match(struct message *mp, struct search_expr const *sep); /* + * ignoretab.c + */ + +/* Add the given header fields to the retained list. If no arguments, print + * the current list of retained fields */ +FL int c_retfield(void *v); + +/* Add the given header fields to the ignored list. If no arguments, print the + * current list of ignored fields */ +FL int c_igfield(void *v); + +FL int c_saveretfield(void *v); +FL int c_saveigfield(void *v); +FL int c_fwdretfield(void *v); +FL int c_fwdigfield(void *v); +FL int c_unignore(void *v); +FL int c_unretain(void *v); +FL int c_unsaveignore(void *v); +FL int c_unsaveretain(void *v); +FL int c_unfwdignore(void *v); +FL int c_unfwdretain(void *v); + +/* See if the given header field (not NUL terminated) is to be ignored. + * For igta: [0] is ignore, [1] is retain -- TODO magic, enwrap in outer obj! */ +FL int is_ign(char const *field, size_t fieldlen, + struct ignoretab igta[2]); + +/* Future object stuff */ + +/* Ignore hashtable lifecycle. + * isauto: whether auto-reclaimed storage is to be used for allocating childs; + * if so, _gut() needn't be called */ +FL struct ignoretab *n_ignoretab_creat(struct ignoretab *self, bool_t isauto); +FL void n_ignoretab_gut(struct ignoretab *self); + +/* Set an entry in an ignore hashtable. + * Returns FAL0 if cp is not a valid header field name, TRU1 if insertion took + * place and TRUM1 if cp is already part of self */ +FL bool_t n_ignoretab_insert(struct ignoretab *self, char const *dat, + size_t len); +#define n_ignoretab_insert_cp(SELF,CP) n_ignoretab_insert(SELF, CP, UIZ_MAX) + +/* */ +FL bool_t n_ignoretab_lookup(struct ignoretab *self, char const *dat, + size_t len); +#define n_ignoretab_lookup_cp(SELF,CP) n_ignoretab_lookup(SELF, CP, UIZ_MAX) + +/* * imap_search.c */ -- 2.11.4.GIT