Clean-up.

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