/*
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 <string.h>
#include <ctype.h>
#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
*
****************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1