/* elmo - ELectronic Mail Operator Copyright (C) 2004 rzyjontko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------- */ /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include "search.h" #include "xmalloc.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ #define MAX_MISTAKES 9 #define MAX_PATTERN_LEN (8 * sizeof (unsigned)) /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ search_t * search_create (int flags, int mistakes) { search_t *search; search = xcalloc (1, sizeof (search_t)); search->mistakes = (mistakes > MAX_MISTAKES) ? MAX_MISTAKES : mistakes; search->flags = flags; search->pattern = str_create_size (MAX_PATTERN_LEN + 1); return search; } void search_destroy (search_t *search) { str_destroy (search->pattern); xfree (search); } int search_add_char (search_t *search, unsigned char c) { int len = search->pattern->len; if (len >= MAX_PATTERN_LEN) return 1; str_put_char (search->pattern, c); if ((search->flags & SEARCH_INSENSITIVE) && isalpha (c)){ search->tab[(int) tolower (c)] |= 1 << len; search->tab[(int) toupper (c)] |= 1 << len; } else { search->tab[(int) c] |= 1 << len; } return 0; } void search_chop (search_t *search) { int len = search->pattern->len - 1; unsigned char c = search->pattern->str[len]; if ((search->flags & SEARCH_INSENSITIVE) && isalpha (c)){ search->tab[(int) tolower (c)] &= ~ (1 << len); search->tab[(int) toupper (c)] &= ~ (1 << len); } else { search->tab[(int) c] &= ~ (1 << len); } str_chop (search->pattern); } int search_perform (search_t *search, const unsigned char *str) { unsigned base[1 + MAX_MISTAKES] = {0, 1, 3, 7, 15, 31, 63, 127, 255, 511}; unsigned tab[1 + MAX_MISTAKES] = {0, 1, 3, 7, 15, 31, 63, 127, 255, 511}; int len; int i, j; int mistakes = search->mistakes; if (search == NULL) return -1; len = strlen (str); for (i = 0; i < len; i++){ for (j = mistakes; j > 0; j--){ tab[j] = base[j] | (tab[j - 1] << 1) | ((1 | tab[j] << 1) & search->tab[(int) str[i]]); } tab[0] = (1 | tab[0] << 1) & search->tab[(int) str[i]]; if (tab[mistakes] & (1 << (search->pattern->len - 1))) return i; } return -1; } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE search.c * ****************************************************************************/