fix problems iterating backwards with start-with pattern

This commit is contained in:
Eric House 2020-08-07 11:05:58 -07:00
parent e5dd43ee1b
commit e8175d69aa
4 changed files with 42 additions and 28 deletions

View file

@ -59,7 +59,7 @@ public class DictBrowseDelegate extends DelegateBase
implements View.OnClickListener { implements View.OnClickListener {
private static final String TAG = DictBrowseDelegate.class.getSimpleName(); private static final String TAG = DictBrowseDelegate.class.getSimpleName();
private static final String DELIM = "."; private static final String DELIM = ".";
private static final boolean SHOW_NUM = false; private static final boolean SHOW_NUM = BuildConfig.DEBUG;
private static final String[] FAQ_PARAMS = {"filters", "intro"}; private static final String[] FAQ_PARAMS = {"filters", "intro"};
private static final String DICT_NAME = "DICT_NAME"; private static final String DICT_NAME = "DICT_NAME";
@ -159,7 +159,8 @@ public class DictBrowseDelegate extends DelegateBase
String str = XwJNI.di_nthWord( m_diClosure, position, m_browseState.m_delim ); String str = XwJNI.di_nthWord( m_diClosure, position, m_browseState.m_delim );
if ( null != str ) { if ( null != str ) {
if ( SHOW_NUM ) { if ( SHOW_NUM ) {
str = String.format( "%1$5d %2$s", position, str ); // Yep, 7 digits. Polish.
str = String.format( "%1$7d %2$s", 1+position, str );
} }
text.setText( str ); text.setText( str );
text.setOnClickListener( DictBrowseDelegate.this ); text.setOnClickListener( DictBrowseDelegate.this );

View file

@ -2818,12 +2818,12 @@ Java_org_eehouse_android_xw4_jni_XwJNI_di_1getIndices
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_di_1nthWord Java_org_eehouse_android_xw4_jni_XwJNI_di_1nthWord
( JNIEnv* env, jclass C, jlong closure, jint nn, jstring jdelim ) ( JNIEnv* env, jclass C, jlong closure, jint jposn, jstring jdelim )
{ {
jstring result = NULL; jstring result = NULL;
DI_HEADER(XP_TRUE); DI_HEADER(XP_TRUE);
if ( NULL != data ) { if ( NULL != data ) {
if ( di_getNthWord( data->iter, env, nn, data->depth, &data->idata ) ) { if ( di_getNthWord( data->iter, env, jposn, data->depth, &data->idata ) ) {
XP_UCHAR buf[64]; XP_UCHAR buf[64];
const XP_UCHAR* delim = NULL == jdelim ? NULL const XP_UCHAR* delim = NULL == jdelim ? NULL
: (*env)->GetStringUTFChars( env, jdelim, NULL ); : (*env)->GetStringUTFChars( env, jdelim, NULL );
@ -2832,6 +2832,8 @@ Java_org_eehouse_android_xw4_jni_XwJNI_di_1nthWord
if ( !!delim ) { if ( !!delim ) {
(*env)->ReleaseStringUTFChars( env, jdelim, delim ); (*env)->ReleaseStringUTFChars( env, jdelim, delim );
} }
} else {
XP_LOGFF( "failed to get %dth word", jposn );
} }
} }
DI_HEADER_END(); DI_HEADER_END();

View file

@ -604,6 +604,15 @@ formatCurWord( const DictIter* iter, XP_UCHAR* buf, XP_U16 bufLen )
} }
} }
/* static void */
/* logCurWord( const DictIter* iter, const XP_UCHAR* note ) */
/* { */
/* XP_UCHAR buf[32]; */
/* XP_U16 bufLen = VSIZE(buf); */
/* formatCurWord( iter, buf, bufLen ); */
/* XP_LOGFF( "note: %s; word: %s", note, buf ); */
/* } */
#endif #endif
typedef struct _FaceTile { typedef struct _FaceTile {
@ -979,7 +988,6 @@ patMatchFinished( const DictIter* iter, XP_Bool log )
XP_UCHAR word[32]; XP_UCHAR word[32];
formatCurWord( iter, word, VSIZE(word) ); formatCurWord( iter, word, VSIZE(word) );
if ( result ) { if ( result ) {
XP_UCHAR elemBuf[64]; XP_UCHAR elemBuf[64];
PrintState prs = { .iter = iter, .buf = elemBuf, .bufLen = VSIZE(elemBuf), }; PrintState prs = { .iter = iter, .buf = elemBuf, .bufLen = VSIZE(elemBuf), };
@ -995,14 +1003,14 @@ patMatchFinished( const DictIter* iter, XP_Bool log )
} }
static XP_Bool static XP_Bool
prevPeerMatch( DictIter* iter, array_edge** edgeP, PatMatch* matchP ) prevPeerMatch( DictIter* iter, array_edge** edgeP, PatMatch* matchP, XP_Bool log )
{ {
const DictionaryCtxt* dict = iter->dict; const DictionaryCtxt* dict = iter->dict;
array_edge* edge = *edgeP; array_edge* edge = *edgeP;
XP_Bool found = XP_FALSE; XP_Bool found = XP_FALSE;
for ( ; ; ) { for ( ; ; ) {
PatMatch match = { 0 }; PatMatch match = { 0 };
found = HAS_MATCH( iter, edge, &match, XP_FALSE ); found = HAS_MATCH( iter, edge, &match, log );
if ( found ) { if ( found ) {
*edgeP = edge; *edgeP = edge;
*matchP = match; *matchP = match;
@ -1131,11 +1139,10 @@ isFirstEdge( const DictionaryCtxt* dict, array_edge* edge )
return result; return result;
} }
static XP_Bool static void
lastEdges( DictIter* iter ) pushLastEdges( DictIter* iter, array_edge* edge, XP_Bool log )
{ {
const DictionaryCtxt* dict = iter->dict; const DictionaryCtxt* dict = iter->dict;
array_edge* edge = popEdge( iter );
while ( iter->nEdges < iter->max ) { while ( iter->nEdges < iter->max ) {
/* walk to the end ... */ /* walk to the end ... */
@ -1144,7 +1151,7 @@ lastEdges( DictIter* iter )
} }
/* ... so we can then move back, testing */ /* ... so we can then move back, testing */
PatMatch match = {0}; PatMatch match = {0};
if ( ! prevPeerMatch( iter, &edge, &match ) ) { if ( ! prevPeerMatch( iter, &edge, &match, log ) ) {
break; break;
} }
pushEdge( iter, edge, &match ); pushEdge( iter, edge, &match );
@ -1154,13 +1161,13 @@ lastEdges( DictIter* iter )
break; break;
} }
} }
return ACCEPT_ITER( iter, XP_FALSE );
} }
static XP_Bool static XP_Bool
prevWord( DictIter* iter, XP_Bool log ) prevWord( DictIter* iter, XP_Bool log )
{ {
const DictionaryCtxt* dict = iter->dict; const DictionaryCtxt* dict = iter->dict;
XP_Bool success = XP_FALSE; XP_Bool success = XP_FALSE;
while ( 0 < iter->nEdges && ! success ) { while ( 0 < iter->nEdges && ! success ) {
if ( isFirstEdge( dict, iter->stack[iter->nEdges-1].edge ) ) { if ( isFirstEdge( dict, iter->stack[iter->nEdges-1].edge ) ) {
@ -1173,20 +1180,14 @@ prevWord( DictIter* iter, XP_Bool log )
array_edge* edge = popEdge(iter); array_edge* edge = popEdge(iter);
XP_ASSERT( !isFirstEdge( dict, edge ) ); XP_ASSERT( !isFirstEdge( dict, edge ) );
edge -= dict->nodeSize; edge -= dict->nodeSize;
PatMatch match = {0}; PatMatch match = {0};
if ( prevPeerMatch( iter, &edge, &match ) ) { if ( prevPeerMatch( iter, &edge, &match, log ) ) {
pushEdge( iter, edge, &match ); pushEdge( iter, edge, &match );
if ( iter->nEdges < iter->max ) { if ( iter->nEdges < iter->max ) {
edge = dict_follow( dict, edge ); edge = dict_follow( dict, edge );
if ( NULL != edge ) { if ( NULL != edge ) {
PatMatch match = {0}; pushLastEdges( iter, edge, log );
if ( HAS_MATCH( iter, edge, &match, log ) ) {
pushEdge( iter, edge, &match );
success = lastEdges( iter ) && iter->min <= iter->nEdges;
if ( success ) {
continue;
}
}
} }
} }
} }
@ -1757,11 +1758,21 @@ di_getNextWord( DictIter* iter )
XP_Bool XP_Bool
di_lastWord( DictIter* iter ) di_lastWord( DictIter* iter )
{ {
ASSERT_INITED( iter ); const XP_Bool log = XP_FALSE;
iter->nEdges = 1;
iter->stack[0].edge = dict_getTopEdge( iter->dict );
XP_Bool success = lastEdges( iter ) || prevWord( iter, XP_FALSE ); ASSERT_INITED( iter );
while ( 0 < iter->nEdges ) {
popEdge( iter );
}
pushLastEdges( iter, dict_getTopEdge( iter->dict ), log );
XP_Bool success = ACCEPT_ITER( iter, log )
&& iter->min <= iter->nEdges
&& iter->nEdges <= iter->max;
if ( !success ) {
success = prevWord( iter, log );
}
if ( success ) { if ( success ) {
iter->position = iter->nWords - 1; iter->position = iter->nWords - 1;
} }
@ -1848,8 +1859,8 @@ di_getNthWord( DictIter* iter, XWEnv xwe, DictPosition position, XP_U16 depth,
} }
while ( repeats-- ) { while ( repeats-- ) {
if ( !(*finder)( iter, XP_FALSE ) ) { if ( !(*finder)( iter, XP_FALSE ) ) {
break; XP_ASSERT(0);
XP_ASSERT(0); /* firing */ break; /* prevents crash on release builds? */
} }
} }

View file

@ -2014,7 +2014,7 @@ patsParamsToIter( const LaunchParams* params, const DictionaryCtxt* dict )
} }
DictIter* iter = di_makeIter( dict, NULL_XWE, dimmp, strPats, nStrPats, DictIter* iter = di_makeIter( dict, NULL_XWE, dimmp, strPats, nStrPats,
descs, nPatDescs ); 0 == nPatDescs ? NULL : descs, nPatDescs );
return iter; return iter;
} }