handle synonyms in non-special tiles for Android: wordlists load and

display, and searching using lower case works.  Specials (e.g. Catalan
changes) not yet supported.
This commit is contained in:
Eric House 2013-04-14 11:58:11 -07:00
parent 2873d08974
commit cae631eeb0
4 changed files with 84 additions and 25 deletions

View file

@ -216,36 +216,42 @@ static void
splitFaces_via_java( JNIEnv* env, AndDictionaryCtxt* ctxt, const XP_U8* ptr,
int nFaceBytes, int nFaces, XP_Bool isUTF8 )
{
XP_UCHAR facesBuf[nFaces*4]; /* seems a reasonable upper bound... */
XP_UCHAR facesBuf[nFaces*16]; /* seems a reasonable upper bound... */
int indx = 0;
int offsets[nFaces];
int nBytes;
int ii;
int ii, jj;
jobject jstrarr = and_util_splitFaces( ctxt->jniutil, ptr, nFaceBytes,
isUTF8 );
XP_ASSERT( (*env)->GetArrayLength( env, jstrarr ) == nFaces );
for ( ii = 0; ii < nFaces; ++ii ) {
jobject jstr = (*env)->GetObjectArrayElement( env, jstrarr, ii );
jobject jstrs = (*env)->GetObjectArrayElement( env, jstrarr, ii );
offsets[ii] = indx;
nBytes = (*env)->GetStringUTFLength( env, jstr );
int nAlternates = (*env)->GetArrayLength( env, jstrs );
for ( jj = 0; jj < nAlternates; ++jj ) {
jobject jstr = (*env)->GetObjectArrayElement( env, jstrs, jj );
nBytes = (*env)->GetStringUTFLength( env, jstr );
const char* bytes = (*env)->GetStringUTFChars( env, jstr, NULL );
char* end;
long numval = strtol( bytes, &end, 10 );
if ( end > bytes ) {
XP_ASSERT( numval < 32 );
nBytes = 1;
facesBuf[indx] = (XP_UCHAR)numval;
} else {
XP_MEMCPY( &facesBuf[indx], bytes, nBytes );
const char* bytes = (*env)->GetStringUTFChars( env, jstr, NULL );
char* end;
long numval = strtol( bytes, &end, 10 );
if ( end > bytes ) {
XP_ASSERT( numval < 32 );
XP_ASSERT( jj == 0 );
nBytes = 1;
facesBuf[indx] = (XP_UCHAR)numval;
} else {
XP_MEMCPY( &facesBuf[indx], bytes, nBytes );
}
(*env)->ReleaseStringUTFChars( env, jstr, bytes );
deleteLocalRef( env, jstr );
indx += nBytes;
facesBuf[indx++] = '\0';
}
(*env)->ReleaseStringUTFChars( env, jstr, bytes );
deleteLocalRef( env, jstr );
indx += nBytes;
facesBuf[indx++] = '\0';
deleteLocalRef( env, jstrs );
XP_ASSERT( indx < VSIZE(facesBuf) );
}
deleteLocalRef( env, jstrarr );
@ -261,6 +267,7 @@ splitFaces_via_java( JNIEnv* env, AndDictionaryCtxt* ctxt, const XP_U8* ptr,
XP_ASSERT( !ctxt->super.faces );
ctxt->super.faces = faces;
ctxt->super.facesEnd = faces + indx;
XP_ASSERT( !ctxt->super.facePtrs );
ctxt->super.facePtrs = ptrs;
} /* splitFaces_via_java */
@ -348,16 +355,30 @@ parseDict( AndDictionaryCtxt* ctxt, XP_U8 const* ptr, XP_U32 dictLength,
JNIEnv* env = ctxt->env;
jstring jsum = and_util_getMD5SumFor( ctxt->jniutil, ctxt->super.name,
NULL, 0 );
XP_UCHAR* md5Sum = NULL;
/* If we have a cached sum, check that it's correct. */
if ( NULL != jsum && NULL != ctxt->super.md5Sum ) {
md5Sum = getStringCopy( MPPARM(ctxt->super.mpool) env, jsum );
if ( 0 != XP_STRCMP( ctxt->super.md5Sum, md5Sum ) ) {
deleteLocalRef( env, jsum );
jsum = NULL;
XP_FREE( ctxt->super.mpool, md5Sum );
md5Sum = NULL;
}
}
if ( NULL == jsum ) {
jsum = and_util_getMD5SumFor( ctxt->jniutil, ctxt->super.name,
ptr, end - ptr );
}
XP_UCHAR* md5Sum = getStringCopy( MPPARM(ctxt->super.mpool) env, jsum );
if ( NULL == md5Sum ) {
md5Sum = getStringCopy( MPPARM(ctxt->super.mpool) env, jsum );
}
deleteLocalRef( env, jsum );
if ( NULL == ctxt->super.md5Sum ) {
ctxt->super.md5Sum = md5Sum;
} else {
XP_ASSERT( 0 == XP_STRCMP( ctxt->super.md5Sum, md5Sum ) );
XP_FREE( ctxt->super.mpool, md5Sum );
}
}

View file

@ -82,7 +82,7 @@ and_util_splitFaces( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len,
JNIEnv* env = *jniutil->envp;
jmethodID mid
= getMethodID( env, jniutil->jjniutil, "splitFaces",
"([BZ)[Ljava/lang/String;" );
"([BZ)[[Ljava/lang/String;" );
jbyteArray jbytes = makeByteArray( env, len, (jbyte*)bytes );
strarray =

View file

@ -25,6 +25,6 @@ import android.graphics.drawable.BitmapDrawable;
public interface JNIUtils {
// Stuff I can't do in C....
String[] splitFaces( byte[] chars, boolean isUTF8 );
String[][] splitFaces( byte[] chars, boolean isUTF8 );
String getMD5SumFor( String dictName, byte[] bytes );
}

View file

@ -28,10 +28,14 @@ import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.util.ArrayList;
import junit.framework.Assert;
import org.eehouse.android.xw4.*;
public class JNIUtilsImpl implements JNIUtils {
private static final char SYNONYM_DELIM = ' ';
private static JNIUtilsImpl s_impl = null;
private Context m_context;
@ -51,10 +55,15 @@ public class JNIUtilsImpl implements JNIUtils {
* convert into individual strings. The 0 is the problem: it's
* not valid utf8. So turn it and the other nums into strings and
* catch them on the other side.
*
* Changes for "synonyms" (A and a being the same tile): return an
* array of Strings for each face. Each face is
* <letter>[<delim><letter]*, so for each loop until the delim
* isn't found.
*/
public String[] splitFaces( byte[] chars, boolean isUTF8 )
public String[][] splitFaces( byte[] chars, boolean isUTF8 )
{
ArrayList<String> al = new ArrayList<String>();
ArrayList<String[]> faces = new ArrayList<String[]>();
ByteArrayInputStream bais = new ByteArrayInputStream( chars );
InputStreamReader isr;
try {
@ -66,6 +75,9 @@ public class JNIUtilsImpl implements JNIUtils {
int[] codePoints = new int[1];
// "A aB bC c"
boolean lastWasDelim = false;
ArrayList<String> face = null;
for ( ; ; ) {
int chr = -1;
try {
@ -74,7 +86,12 @@ public class JNIUtilsImpl implements JNIUtils {
DbgUtils.logf( ioe.toString() );
}
if ( -1 == chr ) {
addFace( faces, face );
break;
} else if ( SYNONYM_DELIM == chr ) {
Assert.assertNotNull( face );
lastWasDelim = true;
continue;
} else {
String letter;
if ( chr < 32 ) {
@ -83,14 +100,35 @@ public class JNIUtilsImpl implements JNIUtils {
codePoints[0] = chr;
letter = new String( codePoints, 0, 1 );
}
al.add( letter );
// Ok, we have a letter. Is it part of an existing
// one or the start of a new? If the latter, insert
// what we have before starting over.
if ( null == face ) { // start of a new, clearly
// do nothing
} else {
Assert.assertTrue( 0 < face.size() );
if ( !lastWasDelim ) {
addFace( faces, face );
face = null;
}
}
lastWasDelim = false;
if ( null == face ) {
face = new ArrayList<String>();
}
face.add( letter );
}
}
String[] result = al.toArray( new String[al.size()] );
String[][] result = faces.toArray( new String[faces.size()][] );
return result;
}
private void addFace( ArrayList<String[]> faces, ArrayList<String> face )
{
faces.add( face.toArray( new String[face.size()] ) );
}
public String getMD5SumFor( String dictName, byte[] bytes )
{
String result = null;