/******************************************************************************
Snippet: Soundex parser.
Author: Richard Woolcock (aka KaVir).
Date: 20th December 2000.
******************************************************************************
This code is copyright (C) 2000 by Richard Woolcock. It may be used and
distributed freely, as long as you don't remove this copyright notice.
******************************************************************************/
/***************************************************************************
* _/ _/ *
* _/_/_/ _/_/ _/_/_/ _/ _/_/ _/ _/ _/_/_/ *
* _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ *
* _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ *
* _/ _/ _/ _/_/_/ _/ _/_/ _/_/_/ _/_/_/ *
***************************************************************************
* Mindcloud Copyright 2001-2003 by Jeff Boschee (Zarius), *
* Additional credits are in the help file CODECREDITS *
* All Rights Reserved. *
***************************************************************************/
/******************************************************************************
Required library files.
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "merc.h"
/******************************************************************************
Local literals
******************************************************************************/
#define KEY_SIZE 4 /* Size of the soundex key */
/******************************************************************************
Local operation prototypes.
******************************************************************************/
static char LetterConversion ( char chLetter );
/******************************************************************************
Global operations.
******************************************************************************/
/* Function: GetSoundexKey
*
* This function determines a soundex key from the string argument and returns
* the address of the key (which is stored in a static variable). Because the
* most common use of the soundex key is to compare it with _another_ soundex
* key, this function uses two internal storage buffers, which are alternated
* between every time the function is called.
*
* The function takes one parameter, as follows:
*
* szTxt: A pointer to the string from which the soundex key is calculated.
*
* The return value is a pointer to the soundex key string.
*/
char *GetSoundexKey( const char *szTxt )
{
int iOldIndex = 0; /* Loop index for the old (szTxt) string */
int iNewIndex = 0; /* Loop index for the new (s_a_chSoundex) string */
static char s_a_chSoundex[2][KEY_SIZE+1]; /* Stores the new string */
static unsigned iSoundex; /* Determines which s_a_chSoundex is used */
iSoundex++; /* Switch to the other s_a_chSoundex array */
s_a_chSoundex[iSoundex%2][0] = '\0'; /* Clear any previous data */
/* Copy the first character without conversion */
if ( ( s_a_chSoundex[iSoundex%2][iNewIndex++] = tolower(szTxt[iOldIndex++]) ) )
{
do /* Loop through szTxt */
{
char chLetter; /* Stores the soundex value of a letter */
/* Double/triple/etc letters are treated as single letters */
while ( tolower(szTxt[iOldIndex]) == tolower(szTxt[iOldIndex+1]) )
{
iOldIndex++;
continue;
}
/* Convert the letter into its soundex value and store it */
chLetter = LetterConversion((char)tolower(szTxt[iOldIndex]));
/* Ignore NUL and 0 characters and only store KEY_SIZE characters */
if ( chLetter != '\0' && chLetter != '0' && iNewIndex < KEY_SIZE )
{
/* Store the soundex value */
s_a_chSoundex[iSoundex%2][iNewIndex++] = chLetter;
}
}
while ( szTxt[iOldIndex++] != '\0' );
/* If less than KEY_SIZE characters were copied, buffer with zeros */
while ( iNewIndex < KEY_SIZE )
{
s_a_chSoundex[iSoundex%2][iNewIndex++] = '0';
}
/* Add the NUL terminator to the end of the soundex string */
s_a_chSoundex[iSoundex%2][iNewIndex] = '\0';
}
/* Return the address of the soundex string */
return ( s_a_chSoundex[iSoundex%2] );
}
/* Function: SoundexMatch
*
* This function compares two soundex keys and returns a percentage match.
*
* The function takes two parameters, as follows:
*
* szFirst: A pointer to the first soundex key.
* szSecond: A pointer to the second soundex key.
*
* The return value is an integer which contains the percentage match.
*/
int SoundexMatch( char *szFirst, char *szSecond )
{
int iMatch = 0; /* Number of matching characters found */
int iMax = 0; /* Total number of characters compared */
/* Make sure that both strings are of the correct size */
if ( strlen( szFirst ) == KEY_SIZE && strlen( szSecond ) == KEY_SIZE )
{
int i; /* Loop counter */
/* Loop through both strings */
for ( i = 0; i < KEY_SIZE; i++ )
{
/* If either of the values are not NUL */
if ( szFirst[i] != '0' || szSecond[i] != '0' )
{
iMax++; /* Increment the maximum */
}
/* If BOTH values are not NUL */
if ( szFirst[i] != '0' && szSecond[i] != '0' )
{
/* Check for a match */
if ( szFirst[i] == szSecond[i] )
{
iMatch++; /* A match was found */
}
}
}
}
/* Return the percentage match */
return ( iMatch * 100 / iMax );
}
/******************************************************************************
Local operations.
******************************************************************************/
/* Function: LetterConversion
*
* This function converts a single letter into it's appropriate soundex value.
*
* The function takes one parameter, as follows:
*
* chLetter: The letter to be converted.
*
* The return value is a single character which contains the converted value.
*/
static char LetterConversion( char chLetter )
{
const char * kszSoundexData = "01230120022455012623010202";
char chResult; /* Store the soundex value, or NUL */
if ( islower(chLetter) )
{
/* Determine the soundex value associated with the letter */
chResult = kszSoundexData[ (chLetter - 'a') ];
}
else /* it's not a lowercase letter */
{
/* NUL means there is no associated soundex value */
chResult = '\0';
}
/* Return the soundex value, or NUL if there isn't one */
return ( chResult );
}