/******************************************************************************
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);
}