Fix prefix matching to accept letters constituting the first part of a

digraph tile when at the end of a prefix so that e.g. GORIL in Catalan
will list GORIL·LA (rather than nothing since GORIL, ending with the L
tile, is not a prefix.)
This commit is contained in:
Eric House 2012-08-27 21:50:09 -07:00
parent fddd2c4ed5
commit 145317426d
4 changed files with 90 additions and 57 deletions

View file

@ -1568,13 +1568,9 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1getStartsWith
jint result = -1;
DictIterData* data = (DictIterData*)closure;
if ( NULL != data ) {
Tile tiles[MAX_COLS];
XP_U16 nTiles = VSIZE(tiles);
const char* prefix = (*env)->GetStringUTFChars( env, jprefix, NULL );
if ( dict_tilesForString( data->dict, prefix, tiles, &nTiles ) ) {
if ( dict_findStartsWith( &data->iter, NULL, tiles, nTiles ) ) {
result = dict_getPosition( &data->iter );
}
if ( 0 <= dict_findStartsWith( &data->iter, prefix ) ) {
result = dict_getPosition( &data->iter );
}
(*env)->ReleaseStringUTFChars( env, jprefix, prefix );
}

View file

@ -170,7 +170,7 @@ prevWord( DictIter* iter )
}
static XP_Bool
findStartsWith( DictIter* iter, const Tile* tiles, XP_U16 nTiles )
findStartsWithTiles( DictIter* iter, const Tile* tiles, XP_U16 nTiles )
{
const DictionaryCtxt* dict = iter->dict;
array_edge* edge = dict_getTopEdge( dict );
@ -189,6 +189,44 @@ findStartsWith( DictIter* iter, const Tile* tiles, XP_U16 nTiles )
return 0 == nTiles;
}
static XP_S16
findStartsWithChars( DictIter* iter, const XP_UCHAR* chars, XP_U16 charsOffset,
array_edge* edge, XP_U16 nTilesUsed )
{
XP_S16 result = -1;
if ( NULL == edge || ( '\0' == chars[charsOffset] ) ) {
iter->nEdges = nTilesUsed;
result = charsOffset;
} else {
const DictionaryCtxt* dict = iter->dict;
XP_U16 nodeSize = dict->nodeSize;
XP_U16 charsLen = XP_STRLEN( &chars[charsOffset] );
for ( ; ; ) {
Tile tile = EDGETILE( dict, edge );
const XP_UCHAR* facep = dict_getTileString( dict, tile );
XP_U16 faceLen = XP_STRLEN( facep );
if ( faceLen > charsLen ) {
faceLen = charsLen;
}
if ( 0 == XP_STRNCMP( facep, &chars[charsOffset], faceLen ) ) {
XP_S16 newOffset = findStartsWithChars( iter, chars,
charsOffset + faceLen,
dict_follow( dict, edge ),
nTilesUsed + 1 );
if ( result < newOffset ) {
iter->edges[nTilesUsed] = edge;
result = newOffset;
}
}
if ( IS_LAST_EDGE( dict, edge ) ) {
break;
}
edge += nodeSize;
}
}
return result;
}
static XP_Bool
startsWith( const DictIter* iter, const Tile* tiles, XP_U16 nTiles )
{
@ -203,7 +241,7 @@ static XP_Bool
findWordStartsWith( DictIter* iter, const Tile* tiles, XP_U16 nTiles )
{
XP_Bool found = XP_FALSE;
if ( findStartsWith( iter, tiles, nTiles ) ) {
if ( findStartsWithTiles( iter, tiles, nTiles ) ) {
found = ACCEPT_ITER( iter, iter->nEdges );
if ( !found ) {
found = nextWord( iter ) && startsWith( iter, tiles, nTiles );
@ -586,37 +624,41 @@ dict_getNthWord( DictIter* iter, DictPosition position, XP_U16 depth,
return success;
} /* dict_getNthWord */
XP_Bool
dict_findStartsWith( DictIter* iter, const IndexData* data,
const Tile* prefix, XP_U16 len )
static DictPosition
figurePosition( DictIter* iter )
{
XP_Bool success = XP_FALSE;
ASSERT_INITED( iter );
XP_USE(data);
XP_LOGF( "%s: not using data", __func__ );
DictPosition result = 0;
DictIter iterZero;
dict_initIterFrom( &iterZero, iter );
if ( !firstWord( &iterZero ) ) {
XP_ASSERT( 0 );
}
DictIter targetIter;
dict_initIterFrom( &targetIter, iter );
if ( findWordStartsWith( &targetIter, prefix, len ) ) {
DictPosition result = 0;
DictIter iterZero;
dict_initIterFrom( &iterZero, iter );
if ( !firstWord( &iterZero ) ) {
while ( ! wordsEqual( &iterZero, iter ) ) {
++result;
if ( !nextWord( &iterZero ) ) {
XP_ASSERT( 0 );
}
while ( ! wordsEqual( &iterZero, &targetIter ) ) {
++result;
if ( !nextWord( &iterZero ) ) {
XP_ASSERT( 0 );
}
}
copyIter( iter, &iterZero );
iter->position = result;
success = XP_TRUE;
}
return success;
copyIter( iter, &iterZero );
return result;
}
XP_S16
dict_findStartsWith( DictIter* iter, const XP_UCHAR* prefix )
{
ASSERT_INITED( iter );
array_edge* edge = dict_getTopEdge( iter->dict );
XP_S16 offset = findStartsWithChars( iter, prefix, 0, edge, 0 );
if ( 0 < offset ) {
if ( nextWord( iter ) ) {
DictPosition result = figurePosition( iter );
iter->position = result;
} else {
offset = -1;
}
}
return offset;
}
void

View file

@ -74,8 +74,7 @@ XP_Bool dict_getPrevWord( DictIter* iter );
XP_Bool dict_getNthWord( DictIter* iter, DictPosition position, XP_U16 depth,
const IndexData* data );
void dict_wordToString( const DictIter* iter, XP_UCHAR* buf, XP_U16 buflen );
XP_Bool dict_findStartsWith( DictIter* iter, const IndexData* data,
const Tile* prefix, XP_U16 len );
XP_S16 dict_findStartsWith( DictIter* iter, const XP_UCHAR* prefix );
DictPosition dict_getPosition( const DictIter* iter );
#ifdef CPLUS
}

View file

@ -1305,31 +1305,27 @@ walk_dict_test( const LaunchParams* XP_UNUSED_DBG(params),
guint count = g_slist_length( testPrefixes );
for ( ii = 0; ii < count; ++ii ) {
gchar* prefix = (gchar*)g_slist_nth_data( testPrefixes, ii );
Tile tiles[MAX_COLS_DICT];
XP_U16 nTiles = VSIZE(tiles);
if ( dict_tilesForString( dict, prefix, tiles, &nTiles ) ) {
if ( dict_findStartsWith( &iter, NULL, tiles, nTiles ) ) {
XP_UCHAR buf[32];
XP_UCHAR bufPrev[32] = {0};
dict_wordToString( &iter, buf, VSIZE(buf) );
XP_S16 lenMatched = dict_findStartsWith( &iter, prefix );
if ( 0 < lenMatched ) {
XP_UCHAR buf[32];
XP_UCHAR bufPrev[32] = {0};
dict_wordToString( &iter, buf, VSIZE(buf) );
XP_ASSERT( 0 == strncmp( buf, prefix, strlen(prefix) ) );
XP_ASSERT( 0 == strncmp( buf, prefix, lenMatched ) );
DictPosition pos = dict_getPosition( &iter );
XP_ASSERT( 0 == strcmp( buf, words[pos] ) );
if ( pos > 0 ) {
if ( !dict_getNthWord( &iter, pos-1, depth,
&data ) ) {
XP_ASSERT( 0 );
}
dict_wordToString( &iter, bufPrev, VSIZE(bufPrev) );
XP_ASSERT( 0 == strcmp( bufPrev, words[pos-1] ) );
DictPosition pos = dict_getPosition( &iter );
XP_ASSERT( 0 == strncmp( buf, words[pos], lenMatched ) );
if ( pos > 0 ) {
if ( !dict_getNthWord( &iter, pos-1, depth, &data ) ) {
XP_ASSERT( 0 );
}
XP_LOGF( "dict_getStartsWith(%s) => %s (prev=%s)",
prefix, buf, bufPrev );
} else {
XP_LOGF( "nothing starts with %s", prefix );
dict_wordToString( &iter, bufPrev, VSIZE(bufPrev) );
XP_ASSERT( 0 == strcmp( bufPrev, words[pos-1] ) );
}
XP_LOGF( "dict_getStartsWith(%s) => %s (prev=%s)",
prefix, buf, bufPrev );
} else {
XP_LOGF( "nothing starts with %s", prefix );
}
}