diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 5ba7f4cc2..abc439271 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -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 ); } diff --git a/xwords4/common/dictiter.c b/xwords4/common/dictiter.c index 9f51fc92b..9315fa0a4 100644 --- a/xwords4/common/dictiter.c +++ b/xwords4/common/dictiter.c @@ -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 diff --git a/xwords4/common/dictiter.h b/xwords4/common/dictiter.h index 61969dd97..6d31d75d8 100644 --- a/xwords4/common/dictiter.h +++ b/xwords4/common/dictiter.h @@ -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 } diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index 6653b0e26..a831f0bf3 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -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 ); } }