Clean-up.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35684 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+242
-292
@@ -32,61 +32,13 @@ names are registered trademarks or trademarks of their respective holders.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include "Words.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <List.h>
|
||||
#include "Words.h"
|
||||
|
||||
/*
|
||||
** File METAPHON.C
|
||||
*/
|
||||
|
||||
/*
|
||||
** MAXMETAPH is the length of the Metaphone code.
|
||||
**
|
||||
** Four is a good compromise value for English names. For comparing words
|
||||
** which are not names or for some non-English names, use a longer code
|
||||
** length for more precise matches.
|
||||
**
|
||||
** The default here is 5.
|
||||
*/
|
||||
|
||||
#define MAXMETAPH 6
|
||||
|
||||
static const char *gCmpKey;
|
||||
static int word_cmp( BString **firstArg, BString **secondArg );
|
||||
|
||||
static int word_cmp( BString **firstArg, BString **secondArg )
|
||||
{
|
||||
return word_match( gCmpKey, (*firstArg)->String() ) - word_match( gCmpKey, (*secondArg)->String() );
|
||||
}
|
||||
|
||||
Words::Words( bool useMetaphone )
|
||||
: fUseMetaphone( useMetaphone )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Words::Words( BPositionIO *thes, bool useMetaphone )
|
||||
: WIndex( thes ),
|
||||
fUseMetaphone( useMetaphone )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Words::~Words( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Words::Words( const char *dataPath, const char *indexPath, bool useMetaphone )
|
||||
: fUseMetaphone( useMetaphone )
|
||||
{
|
||||
if( !useMetaphone )
|
||||
entrySize = sizeof( uint32 );
|
||||
SetTo( dataPath, indexPath );
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -95,9 +47,73 @@ enum
|
||||
GET_FLAGS
|
||||
};
|
||||
|
||||
// Parse the Words file...
|
||||
status_t Words::BuildIndex( void )
|
||||
|
||||
/*
|
||||
MAXMETAPH is the length of the Metaphone code.
|
||||
|
||||
Four is a good compromise value for English names. For comparing words
|
||||
which are not names or for some non-English names, use a longer code
|
||||
length for more precise matches.
|
||||
|
||||
The default here is 5.
|
||||
*/
|
||||
|
||||
#define MAXMETAPH 6
|
||||
|
||||
|
||||
// Character coding array, A-Z
|
||||
static char vsvfn[26] = { 1, 16, 4, 16, 9, 2, 4, 16, 9, 2, 0, 2, 2, 2, 1, 4, 0,
|
||||
2, 4, 4, 1, 0, 0, 0, 8, 0};
|
||||
|
||||
|
||||
static const char* gCmpKey;
|
||||
|
||||
|
||||
static int word_cmp(BString** firstArg, BString** secondArg)
|
||||
{
|
||||
return word_match(gCmpKey, (*firstArg)->String()) - word_match(gCmpKey,
|
||||
(*secondArg)->String());
|
||||
}
|
||||
|
||||
|
||||
Words::Words(bool useMetaphone)
|
||||
:
|
||||
fUseMetaphone(useMetaphone)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Words::Words(BPositionIO* thes, bool useMetaphone)
|
||||
:
|
||||
WIndex(thes),
|
||||
fUseMetaphone(useMetaphone)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Words::~Words(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Words::Words(const char* dataPath, const char* indexPath, bool useMetaphone)
|
||||
:
|
||||
fUseMetaphone(useMetaphone)
|
||||
{
|
||||
if (!useMetaphone)
|
||||
entrySize = sizeof(uint32);
|
||||
SetTo(dataPath, indexPath);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Words::BuildIndex(void)
|
||||
{
|
||||
// Parse the Words file...
|
||||
|
||||
// Buffer Stuff
|
||||
char buffer[16384];
|
||||
char *nptr, *eptr;
|
||||
@@ -118,34 +134,28 @@ status_t Words::BuildIndex( void )
|
||||
entry.offset = -1;
|
||||
|
||||
// Read blocks from thes until eof
|
||||
while( true )
|
||||
{
|
||||
while (true) {
|
||||
// Get next block
|
||||
blockOffset = dataFile->Position();
|
||||
if ((blockSize = dataFile->Read(buffer, 16384)) == 0)
|
||||
break;
|
||||
|
||||
// parse block
|
||||
for( nptr = buffer, eptr = buffer + blockSize; nptr < eptr; nptr++ )
|
||||
{
|
||||
for (nptr = buffer, eptr = buffer + blockSize; nptr < eptr; nptr++) {
|
||||
// Looking for start of word?
|
||||
if( state == FIND_WORD )
|
||||
{
|
||||
if (state == FIND_WORD) {
|
||||
// Is start of word?
|
||||
if( isalpha(*nptr) )
|
||||
{
|
||||
if (isalpha(*nptr)) {
|
||||
state = GET_WORD;
|
||||
*namePtr++ = *nptr; // copy word
|
||||
entry.offset = blockOffset + (nptr - buffer);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
entry.offset++;
|
||||
}
|
||||
} else if ((*nptr == '\n') || (*nptr == '\r')) {
|
||||
// End of word?
|
||||
else if( (*nptr == '\n')||(*nptr == '\r') )
|
||||
{
|
||||
if( namePtr != entryName )
|
||||
{
|
||||
|
||||
if (namePtr != entryName) {
|
||||
// Add previous entry to word index
|
||||
*namePtr = 0; // terminate word
|
||||
*flagsPtr = 0; // terminate flags
|
||||
@@ -155,13 +165,10 @@ status_t Words::BuildIndex( void )
|
||||
AddItem(&entry);
|
||||
|
||||
// Add suffixed words if any
|
||||
if( flagsPtr != flags )
|
||||
{
|
||||
if (flagsPtr != flags) {
|
||||
// printf("Base: %s, flags: %s\n", entryName, flags);
|
||||
for( flagsPtr=flags; *flagsPtr != 0; flagsPtr++ )
|
||||
{
|
||||
if( suffix_word( suffixName, entryName, *flagsPtr ) )
|
||||
{
|
||||
for (flagsPtr = flags; *flagsPtr != 0; flagsPtr++) {
|
||||
if (suffix_word(suffixName, entryName, *flagsPtr)) {
|
||||
// printf("Suffix: %s\n", suffixName);
|
||||
entry.key = GetKey(suffixName);
|
||||
AddItem(&entry);
|
||||
@@ -173,42 +180,31 @@ status_t Words::BuildIndex( void )
|
||||
state = FIND_WORD;
|
||||
namePtr = entryName;
|
||||
flagsPtr = flags;
|
||||
}
|
||||
else if( state == GET_WORD ) // Are we looking for a word?
|
||||
{
|
||||
} else if (state == GET_WORD) {
|
||||
// Start of flags?
|
||||
if( *nptr == '/' )
|
||||
{
|
||||
if (*nptr == '/') {
|
||||
*namePtr = 0; // terminate word
|
||||
// printf("Found word: %s\n", entryName);
|
||||
|
||||
// Set state to get flags
|
||||
state = GET_FLAGS;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
*namePtr++ = *nptr; // copy word
|
||||
}
|
||||
else if( state == GET_FLAGS ) // Are we getting the flags?
|
||||
} else if (state == GET_FLAGS) // Are we getting the flags?
|
||||
*flagsPtr++ = *nptr; // copy flag
|
||||
} // End for( nptr = buffer, eptr = buffer + blockSize; nptr < eptr; nptr++, entry.size++ )
|
||||
} // End for (nptr = buffer, eptr = buffer + blockSize;
|
||||
// nptr < eptr; nptr++, entry.size++)
|
||||
} // End while (true)
|
||||
|
||||
SortItems();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Character coding array
|
||||
*/
|
||||
|
||||
static char vsvfn[26] = {
|
||||
1,16,4,16,9,2,4,16,9,2,0,2,2,2,1,4,0,2,4,4,1,0,0,0,8,0};
|
||||
/* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */
|
||||
|
||||
int32 Words::GetKey( const char *s )
|
||||
{
|
||||
if( fUseMetaphone )
|
||||
int32
|
||||
Words::GetKey(const char* s)
|
||||
{
|
||||
if (fUseMetaphone) {
|
||||
char Metaph[12];
|
||||
const char *sPtr;
|
||||
int32 key = 0;
|
||||
@@ -220,8 +216,7 @@ int32 Words::GetKey( const char *s )
|
||||
|
||||
// printf("%s -> %s: \n", s, Metaph);
|
||||
|
||||
for( sPtr = Metaph, offset = 25; *sPtr; sPtr++, offset -= 5 )
|
||||
{
|
||||
for (sPtr = Metaph, offset = 25; *sPtr; sPtr++, offset -= 5) {
|
||||
c = *sPtr - 'A';
|
||||
// printf("%d,", int16(c));
|
||||
key |= int32(c) << offset;
|
||||
@@ -230,87 +225,78 @@ int32 Words::GetKey( const char *s )
|
||||
key |= int32(31) << offset;
|
||||
// printf(": %ld\n", key);
|
||||
return key;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return WIndex::GetKey(s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Macros to access the character coding array
|
||||
*/
|
||||
|
||||
#define vowel(x) (vsvfn[(x) - 'A'] & 1) /* AEIOU */
|
||||
#define same(x) (vsvfn[(x) - 'A'] & 2) /* FJLMNR */
|
||||
#define varson(x) (vsvfn[(x) - 'A'] & 4) /* CGPST */
|
||||
#define frontv(x) (vsvfn[(x) - 'A'] & 8) /* EIY */
|
||||
#define noghf(x) (vsvfn[(x) - 'A'] & 16) /* BDH */
|
||||
// Macros to access the character coding array
|
||||
#define vowel(x) (vsvfn[(x) - 'A'] & 1) // AEIOU
|
||||
#define same(x) (vsvfn[(x) - 'A'] & 2) // FJLMNR
|
||||
#define varson(x) (vsvfn[(x) - 'A'] & 4) // CGPST
|
||||
#define frontv(x) (vsvfn[(x) - 'A'] & 8) // EIY
|
||||
#define noghf(x) (vsvfn[(x) - 'A'] & 16) // BDH
|
||||
#define NUL '\0'
|
||||
|
||||
/*
|
||||
** metaphone()
|
||||
**
|
||||
** Arguments: 1 - The word to be converted to a metaphone code.
|
||||
** 2 - A MAXMETAPH+1 char field for the result.
|
||||
** 3 - Function flag:
|
||||
** If 0: Compute the Metaphone code for the first argument,
|
||||
** then compare it to the Metaphone code passed in
|
||||
** the second argument.
|
||||
** If 1: Compute the Metaphone code for the first argument,
|
||||
** then store the result in the area pointed to by the
|
||||
** second argument.
|
||||
**
|
||||
** Returns: If function code is 0, returns Success_ for a match, else Error_.
|
||||
** If function code is 1, returns Success_.
|
||||
metaphone()
|
||||
|
||||
Arguments:
|
||||
1 - The word to be converted to a metaphone code.
|
||||
2 - A MAXMETAPH + 1 char field for the result.
|
||||
3 - Function flag:
|
||||
If 0: Compute the Metaphone code for the first argument,
|
||||
then compare it to the Metaphone code passed in the second argument.
|
||||
If 1: Compute the Metaphone code for the first argument,
|
||||
then store the result in the area pointed to by the second argument.
|
||||
|
||||
Returns:
|
||||
If function code is 0, returns Success_ for a match, else Error_.
|
||||
If function code is 1, returns Success_.
|
||||
*/
|
||||
|
||||
bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
|
||||
bool
|
||||
metaphone(const char* Word, char* Metaph, metaphlag Flag)
|
||||
{
|
||||
char *n, *n_start, *n_end; /* Pointers to string */
|
||||
char *metaph = NULL, *metaph_end; /* Pointers to metaph */
|
||||
char ntrans[512]; /* Word with uppercase letters */
|
||||
char newm[MAXMETAPH + 4]; /* New metaph for comparison */
|
||||
int KSflag; /* State flag for X translation */
|
||||
char *n, *n_start, *n_end; // Pointers to string
|
||||
char *metaph = NULL, *metaph_end; // Pointers to metaph
|
||||
char ntrans[512]; // Word with uppercase letters
|
||||
char newm[MAXMETAPH + 4]; // New metaph for comparison
|
||||
int KSflag; // State flag for X translation
|
||||
|
||||
/*
|
||||
** Copy word to internal buffer, dropping non-alphabetic characters
|
||||
** and converting to upper case.
|
||||
*/
|
||||
// Copy word to internal buffer, dropping non-alphabetic characters
|
||||
// and converting to upper case.
|
||||
|
||||
for (n = ntrans + 1, n_end = ntrans + sizeof(ntrans) - 2;
|
||||
*Word && n < n_end; ++Word)
|
||||
{
|
||||
*Word && n < n_end; ++Word) {
|
||||
if (isalpha(*Word))
|
||||
*n++ = toupper(*Word);
|
||||
}
|
||||
|
||||
if (n == ntrans + 1)
|
||||
return false; /* Return if zero characters */
|
||||
else n_end = n; /* Set end of string pointer */
|
||||
return false; // Return if zero characters
|
||||
else
|
||||
n_end = n; // Set end of string pointer
|
||||
|
||||
/*
|
||||
** Pad with NULs, front and rear
|
||||
*/
|
||||
// Pad with NULs, front and rear
|
||||
|
||||
*n++ = NUL;
|
||||
*n = NUL;
|
||||
n = ntrans;
|
||||
*n++ = NUL;
|
||||
|
||||
/*
|
||||
** If doing comparison, redirect pointers
|
||||
*/
|
||||
// If doing comparison, redirect pointers
|
||||
|
||||
if (COMPARE == Flag)
|
||||
{
|
||||
if (COMPARE == Flag) {
|
||||
metaph = Metaph;
|
||||
Metaph = newm;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check for PN, KN, GN, WR, WH, and X at start
|
||||
*/
|
||||
// Check for PN, KN, GN, WR, WH, and X at start
|
||||
|
||||
switch (*n)
|
||||
{
|
||||
switch (*n) {
|
||||
case 'P':
|
||||
case 'K':
|
||||
case 'G':
|
||||
@@ -324,10 +310,9 @@ bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
if ('R' == *(n + 1))
|
||||
if ('R' == *(n + 1)) {
|
||||
*n++ = NUL;
|
||||
else if ('H' == *(n + 1))
|
||||
{
|
||||
} else if ('H' == *(n + 1)) {
|
||||
*(n + 1) = *n;
|
||||
*n++ = NUL;
|
||||
}
|
||||
@@ -338,78 +323,69 @@ bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Now loop through the string, stopping at the end of the string
|
||||
** or when the computed Metaphone code is MAXMETAPH characters long.
|
||||
*/
|
||||
// Now loop through the string, stopping at the end of the string
|
||||
// or when the computed Metaphone code is MAXMETAPH characters long.
|
||||
|
||||
KSflag = false; // State flag for KStranslation
|
||||
|
||||
KSflag = false; /* State flag for KStranslation */
|
||||
for (metaph_end = Metaph + MAXMETAPH, n_start = n;
|
||||
n <= n_end && Metaph < metaph_end; ++n)
|
||||
{
|
||||
if (KSflag)
|
||||
{
|
||||
n <= n_end && Metaph < metaph_end; ++n) {
|
||||
if (KSflag) {
|
||||
KSflag = false;
|
||||
*Metaph++ = *n;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Drop duplicates except for CC */
|
||||
} else {
|
||||
// Drop duplicates except for CC
|
||||
|
||||
if (*(n - 1) == *n && *n != 'C')
|
||||
continue;
|
||||
|
||||
/* Check for F J L M N R or first letter vowel */
|
||||
// Check for F J L M N R or first letter vowel
|
||||
|
||||
if (same(*n) || (n == n_start && vowel(*n)))
|
||||
if (same(*n) || (n == n_start && vowel(*n))) {
|
||||
*Metaph++ = *n;
|
||||
else switch (*n)
|
||||
{
|
||||
} else {
|
||||
switch (*n) {
|
||||
case 'B':
|
||||
if (n < n_end || *(n - 1) != 'M')
|
||||
*Metaph++ = *n;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
if (*(n - 1) != 'S' || !frontv(*(n + 1)))
|
||||
{
|
||||
if (*(n - 1) != 'S' || !frontv(*(n + 1))) {
|
||||
if ('I' == *(n + 1) && 'A' == *(n + 2))
|
||||
*Metaph++ = 'X';
|
||||
else if (frontv(*(n + 1)))
|
||||
*Metaph++ = 'S';
|
||||
else if ('H' == *(n + 1))
|
||||
*Metaph++ = ((n == n_start &&
|
||||
!vowel(*(n + 2))) ||
|
||||
'S' == *(n - 1)) ? 'K' : 'X';
|
||||
else *Metaph++ = 'K';
|
||||
else if ('H' == *(n + 1)) {
|
||||
*Metaph++ = ((n == n_start && !vowel(*(n + 2)))
|
||||
|| 'S' == *(n - 1)) ? 'K' : 'X';
|
||||
} else {
|
||||
*Metaph++ = 'K';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
*Metaph++ = ('G' == *(n + 1) && frontv(*(n + 2))) ?
|
||||
'J' : 'T';
|
||||
*Metaph++ = ('G' == *(n + 1) && frontv(*(n + 2)))
|
||||
? 'J' : 'T';
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
if ((*(n + 1) != 'H' || vowel(*(n + 2))) &&
|
||||
(*(n + 1) != 'N' || ((n + 1) < n_end &&
|
||||
(*(n + 2) != 'E' || *(n + 3) != 'D'))) &&
|
||||
(*(n - 1) != 'D' || !frontv(*(n + 1))))
|
||||
{
|
||||
*Metaph++ = (frontv(*(n + 1)) &&
|
||||
*(n + 2) != 'G') ? 'J' : 'K';
|
||||
}
|
||||
else if ('H' == *(n + 1) && !noghf(*(n - 3)) &&
|
||||
*(n - 4) != 'H')
|
||||
{
|
||||
if ((*(n + 1) != 'H' || vowel(*(n + 2)))
|
||||
&& (*(n + 1) != 'N' || ((n + 1) < n_end
|
||||
&& (*(n + 2) != 'E' || *(n + 3) != 'D')))
|
||||
&& (*(n - 1) != 'D' || !frontv(*(n + 1)))) {
|
||||
*Metaph++ = (frontv(*(n + 1))
|
||||
&& *(n + 2) != 'G') ? 'J' : 'K';
|
||||
} else if ('H' == *(n + 1) && !noghf(*(n - 3))
|
||||
&& *(n - 4) != 'H') {
|
||||
*Metaph++ = 'F';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (!varson(*(n - 1)) && (!vowel(*(n - 1)) ||
|
||||
vowel(*(n + 1))))
|
||||
{
|
||||
if (!varson(*(n - 1))
|
||||
&& (!vowel(*(n - 1)) || vowel(*(n + 1)))) {
|
||||
*Metaph++ = 'H';
|
||||
}
|
||||
break;
|
||||
@@ -428,21 +404,20 @@ bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
*Metaph++ = ('H' == *(n + 1) || ('I' == *(n + 1) &&
|
||||
('O' == *(n + 2) || 'A' == *(n + 2)))) ?
|
||||
'X' : 'S';
|
||||
*Metaph++ = ('H' == *(n + 1) || ('I' == *(n + 1)
|
||||
&& ('O' == *(n + 2) || 'A' == *(n + 2))))
|
||||
? 'X' : 'S';
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if ('I' == *(n + 1) && ('O' == *(n + 2) ||
|
||||
'A' == *(n + 2)))
|
||||
{
|
||||
if ('I' == *(n + 1)
|
||||
&& ('O' == *(n + 2) || 'A' == *(n + 2))) {
|
||||
*Metaph++ = 'X';
|
||||
}
|
||||
else if ('H' == *(n + 1))
|
||||
} else if ('H' == *(n + 1)) {
|
||||
*Metaph++ = 'O';
|
||||
else if (*(n + 1) != 'C' || *(n + 2) != 'H')
|
||||
} else if (*(n + 1) != 'C' || *(n + 2) != 'H') {
|
||||
*Metaph++ = 'T';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
@@ -456,10 +431,9 @@ bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (n == n_start)
|
||||
if (n == n_start) {
|
||||
*Metaph++ = 'S';
|
||||
else
|
||||
{
|
||||
} else {
|
||||
*Metaph++ = 'K';
|
||||
KSflag = true;
|
||||
}
|
||||
@@ -470,22 +444,16 @@ bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare new Metaphone code with old
|
||||
*/
|
||||
|
||||
if (COMPARE == Flag &&
|
||||
*(Metaph - 1) != metaph[(Metaph - newm) - 1])
|
||||
{
|
||||
// Compare new Metaphone code with old
|
||||
if (COMPARE == Flag
|
||||
&& *(Metaph - 1) != metaph[(Metaph - newm) - 1]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If comparing, check if Metaphone codes were equal in length
|
||||
*/
|
||||
|
||||
// If comparing, check if Metaphone codes were equal in length
|
||||
if (COMPARE == Flag && metaph[Metaph - newm])
|
||||
return false;
|
||||
|
||||
@@ -493,7 +461,9 @@ bool metaphone(const char *Word, char *Metaph, metaphlag Flag)
|
||||
return true;
|
||||
}
|
||||
|
||||
int word_match( const char *reference, const char *test )
|
||||
|
||||
int
|
||||
word_match(const char* reference, const char* test)
|
||||
{
|
||||
const char *s1, *s2;
|
||||
int32 x = 0;
|
||||
@@ -503,33 +473,27 @@ int word_match( const char *reference, const char *test )
|
||||
|
||||
bool a, b;
|
||||
|
||||
while( *s2 || *s1 )
|
||||
{
|
||||
while (*s2 || *s1) {
|
||||
c1 = tolower(*s1);
|
||||
c2 = tolower(*s2);
|
||||
|
||||
if( *s2 && *s1 )
|
||||
{
|
||||
if( c1 != c2 )
|
||||
{
|
||||
if (*s2 && *s1) {
|
||||
if (c1 != c2) {
|
||||
a = (tolower(s1[1]) == c2);
|
||||
b = (tolower(s2[1]) == c1);
|
||||
// Reversed pair
|
||||
if( a && b )
|
||||
{
|
||||
if (a && b) {
|
||||
x += 1;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
// Extra character
|
||||
if( a )
|
||||
{
|
||||
if (a) {
|
||||
x += 1;
|
||||
s1++;
|
||||
}
|
||||
// Missing Character
|
||||
else if( b )
|
||||
{
|
||||
else if (b) {
|
||||
x += 1;
|
||||
s2++;
|
||||
}
|
||||
@@ -540,9 +504,10 @@ int word_match( const char *reference, const char *test )
|
||||
else
|
||||
x += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
x += 1;
|
||||
}
|
||||
|
||||
if (*s2)
|
||||
s2++;
|
||||
if (*s1)
|
||||
@@ -552,17 +517,17 @@ int word_match( const char *reference, const char *test )
|
||||
return x;
|
||||
}
|
||||
|
||||
int32 suffix_word( char *dst, const char *src, char flag )
|
||||
|
||||
int32
|
||||
suffix_word(char* dst, const char* src, char flag)
|
||||
{
|
||||
char* end;
|
||||
|
||||
end = stpcpy(dst, src);
|
||||
flag = toupper(flag);
|
||||
switch( flag )
|
||||
{
|
||||
switch(flag) {
|
||||
case 'V':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ive");
|
||||
break;
|
||||
@@ -572,8 +537,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ion");
|
||||
break;
|
||||
@@ -586,8 +550,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ions");
|
||||
break;
|
||||
@@ -600,8 +563,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'y':
|
||||
end = stpcpy(end - 1, "ieth");
|
||||
break;
|
||||
@@ -614,8 +576,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
end = stpcpy(end, "ly");
|
||||
break;
|
||||
case 'G':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ing");
|
||||
break;
|
||||
@@ -625,8 +586,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ings");
|
||||
break;
|
||||
@@ -636,14 +596,12 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ed");
|
||||
break;
|
||||
case 'y':
|
||||
if( !strchr( "aeiou", end[-2] ) )
|
||||
{
|
||||
if (!strchr("aeiou", end[-2])) {
|
||||
end = stpcpy(end - 1, "ied");
|
||||
break;
|
||||
}
|
||||
@@ -654,14 +612,12 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "est");
|
||||
break;
|
||||
case 'y':
|
||||
if( !strchr( "aeiou", end[-2] ) )
|
||||
{
|
||||
if (!strchr("aeiou", end[-2])) {
|
||||
end = stpcpy(end - 1, "iest");
|
||||
break;
|
||||
}
|
||||
@@ -672,14 +628,12 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "er");
|
||||
break;
|
||||
case 'y':
|
||||
if( !strchr( "aeiou", end[-2] ) )
|
||||
{
|
||||
if (!strchr("aeiou", end[-2])) {
|
||||
end = stpcpy(end - 1, "ier");
|
||||
break;
|
||||
}
|
||||
@@ -690,14 +644,12 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'e':
|
||||
end = stpcpy(end - 1, "ers");
|
||||
break;
|
||||
case 'y':
|
||||
if( !strchr( "aeiou", end[-2] ) )
|
||||
{
|
||||
if (!strchr("aeiou", end[-2])) {
|
||||
end = stpcpy(end - 1, "iers");
|
||||
break;
|
||||
}
|
||||
@@ -708,8 +660,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 's':
|
||||
case 'x':
|
||||
case 'z':
|
||||
@@ -717,8 +668,7 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
end = stpcpy(end, "es");
|
||||
break;
|
||||
case 'y':
|
||||
if( !strchr( "aeiou", end[-2] ) )
|
||||
{
|
||||
if (!strchr("aeiou", end[-2])) {
|
||||
end = stpcpy(end - 1, "ies");
|
||||
break;
|
||||
}
|
||||
@@ -729,11 +679,9 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
switch( end[-1] )
|
||||
{
|
||||
switch(end[-1]) {
|
||||
case 'y':
|
||||
if( !strchr( "aeiou", end[-2] ) )
|
||||
{
|
||||
if (!strchr("aeiou", end[-2])) {
|
||||
end = stpcpy(end - 1, "iness");
|
||||
break;
|
||||
}
|
||||
@@ -752,13 +700,14 @@ int32 suffix_word( char *dst, const char *src, char flag )
|
||||
return end - dst;
|
||||
}
|
||||
|
||||
int32 Words::FindBestMatches( BList *matches, const char *s )
|
||||
|
||||
int32
|
||||
Words::FindBestMatches(BList* matches, const char* s)
|
||||
{
|
||||
int32 index;
|
||||
// printf("*** Looking for %s: ***\n", s);
|
||||
|
||||
if( (index = FindFirst( s )) >= 0 )
|
||||
{
|
||||
if ((index = FindFirst(s)) >= 0) {
|
||||
BString srcWord(s);
|
||||
FileEntry* entry;
|
||||
WIndexEntry* indexEntry;
|
||||
@@ -777,8 +726,7 @@ int32 Words::FindBestMatches( BList *matches, const char *s )
|
||||
for (int32 i = 0; i < 32; i++)
|
||||
hashTable[i] = 0;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
indexEntry = ItemAt(index);
|
||||
// Hash the entry offset; we use this to make sure we don't add
|
||||
// the same word file entry twice;
|
||||
@@ -789,11 +737,12 @@ int32 Words::FindBestMatches( BList *matches, const char *s )
|
||||
highHash = hashValue >> 3;
|
||||
lowHash = 0x01 << (hashValue & 0x07);
|
||||
|
||||
//printf( "Testing Entry: %ld: hash=%d, highHash=%d, lowHash=%d\n", indexEntry->offset, hashValue, (uint16)highHash, (uint16)lowHash );
|
||||
// printf("Testing Entry: %ld: hash=%d, highHash=%d, lowHash=%d\n",
|
||||
// indexEntry->offset, hashValue, (uint16)highHash,
|
||||
// (uint16)lowHash);
|
||||
|
||||
// Has this entry offset been seen before?
|
||||
if( !(hashTable[highHash] & lowHash) )
|
||||
{
|
||||
if (!(hashTable[highHash] & lowHash)) {
|
||||
// printf("New Entry\n");
|
||||
hashTable[highHash] |= lowHash; // Mark this offset so we don't add it twice
|
||||
|
||||
@@ -813,50 +762,51 @@ int32 Words::FindBestMatches( BList *matches, const char *s )
|
||||
// printf("Base Word: %s\n", word);
|
||||
// printf("Flags: %s\n", suffixFlags);
|
||||
testWord = word; // Test the base word first
|
||||
do
|
||||
{
|
||||
do {
|
||||
// printf("Testing: %s\n", testWord);
|
||||
// Does this word match the key
|
||||
if( (GetKey( testWord ) == key) &&
|
||||
if ((GetKey(testWord) == key)
|
||||
// And does it look close enough to the compare key?
|
||||
//word_match( gCmpKey, testWord ) <= int32((strlen( gCmpKey )-1)/2) )
|
||||
word_match( gCmpKey, testWord ) <= int32(float(strlen( gCmpKey )-1)*.75) )
|
||||
{
|
||||
// word_match(gCmpKey, testWord)
|
||||
// <= int32((strlen(gCmpKey)-1)/2))
|
||||
&& word_match(gCmpKey, testWord)
|
||||
<= int32(float(strlen(gCmpKey)-1)*.75)) {
|
||||
// printf("Added: %s\n", testWord);
|
||||
matches->AddItem( (void *)(new BString( testWord )) ); // Add it to the list
|
||||
matches->AddItem((void*)(new BString(testWord)));
|
||||
}
|
||||
|
||||
// If suffix, transform and test
|
||||
if( *suffixFlags )
|
||||
{
|
||||
if (*suffixFlags) {
|
||||
// Repeat until valid suffix found or end is reached
|
||||
suffixLength = 0;
|
||||
while( *suffixFlags && !(suffixLength=suffix_word( suffixWord, word, *suffixFlags++ )) ) {}
|
||||
while (*suffixFlags
|
||||
&& !(suffixLength = suffix_word(suffixWord,
|
||||
word, *suffixFlags++))) {}
|
||||
if (suffixLength)
|
||||
testWord = suffixWord;
|
||||
else
|
||||
testWord = NULL;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
testWord = NULL;
|
||||
}
|
||||
} while (testWord);
|
||||
delete entry;
|
||||
}
|
||||
//else
|
||||
//printf( "Redundant entry\n" );
|
||||
// else printf("Redundant entry\n");
|
||||
|
||||
index++;
|
||||
} while (key == (ItemAt(index))->key);
|
||||
|
||||
return matches->CountItems();
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sort_word_list(BList* matches, const char* reference)
|
||||
{
|
||||
if( matches->CountItems() > 0 )
|
||||
{
|
||||
if (matches->CountItems() > 0) {
|
||||
BString srcWord(reference);
|
||||
gCmpKey = srcWord.String();
|
||||
matches->SortItems((int(*)(const void*, const void*))word_cmp);
|
||||
|
||||
@@ -34,27 +34,31 @@ All rights reserved.
|
||||
#ifndef _WORDS_H
|
||||
#define _WORDS_H
|
||||
|
||||
|
||||
#include <List.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "WIndex.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
COMPARE,
|
||||
GENERATE
|
||||
} metaphlag;
|
||||
|
||||
class Words;
|
||||
|
||||
bool metaphone(const char* Word, char* Metaph, metaphlag Flag);
|
||||
int word_match(const char* reference, const char* test);
|
||||
int32 suffix_word(char* dst, const char* src, char flag);
|
||||
void sort_word_list(BList* matches, const char* reference);
|
||||
|
||||
|
||||
class Words : public WIndex {
|
||||
public:
|
||||
Words(bool useMetaphone = true);
|
||||
Words(BPositionIO* thes, bool useMetaphone = true);
|
||||
Words(const char *dataPath, const char *indexPath, bool useMetaphone);
|
||||
Words(const char* dataPath, const char* indexPath,
|
||||
bool useMetaphone);
|
||||
virtual ~Words(void);
|
||||
|
||||
virtual status_t BuildIndex(void);
|
||||
|
||||
Reference in New Issue
Block a user