mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-03 09:49:19 +02:00
fixed encoding conversion for non-1-byte encodings
This commit is contained in:
parent
1523188dd4
commit
482ecca302
5 changed files with 25 additions and 22 deletions
|
@ -149,7 +149,7 @@ bool AndroidUtil::init(JavaVM* jvm) {
|
|||
|
||||
Method_Encoding_createConverter = new ObjectMethod(Class_Encoding, "createConverter", Class_EncodingConverter, "()");
|
||||
Field_EncodingConverter_Name = new ObjectField(Class_EncodingConverter, "Name", Class_java_lang_String);
|
||||
Method_EncodingConverter_convert = new IntMethod(Class_EncodingConverter, "convert", "([BII[BI)");
|
||||
Method_EncodingConverter_convert = new IntMethod(Class_EncodingConverter, "convert", "([BII[C)");
|
||||
Method_EncodingConverter_reset = new VoidMethod(Class_EncodingConverter, "reset", "()");
|
||||
|
||||
StaticMethod_JavaEncodingCollection_Instance = new StaticObjectMethod(Class_JavaEncodingCollection, "Instance", Class_JavaEncodingCollection, "()");
|
||||
|
|
|
@ -39,7 +39,8 @@ private:
|
|||
jobject myJavaConverter;
|
||||
int myBufferLength;
|
||||
jbyteArray myInBuffer;
|
||||
jbyteArray myOutBuffer;
|
||||
jcharArray myOutBuffer;
|
||||
jchar *myCppOutBuffer;
|
||||
|
||||
friend class JavaEncodingConverterProvider;
|
||||
};
|
||||
|
@ -73,11 +74,13 @@ JavaEncodingConverter::JavaEncodingConverter(const std::string &encoding) {
|
|||
|
||||
myBufferLength = 32768;
|
||||
myInBuffer = env->NewByteArray(myBufferLength);
|
||||
myOutBuffer = env->NewByteArray(2 * myBufferLength);
|
||||
myOutBuffer = env->NewCharArray(myBufferLength);
|
||||
myCppOutBuffer = new jchar[myBufferLength];
|
||||
}
|
||||
|
||||
JavaEncodingConverter::~JavaEncodingConverter() {
|
||||
JNIEnv *env = AndroidUtil::getEnv();
|
||||
delete[] myCppOutBuffer;
|
||||
env->DeleteLocalRef(myOutBuffer);
|
||||
env->DeleteLocalRef(myInBuffer);
|
||||
env->DeleteLocalRef(myJavaConverter);
|
||||
|
@ -95,18 +98,26 @@ void JavaEncodingConverter::convert(std::string &dst, const char *srcStart, cons
|
|||
JNIEnv *env = AndroidUtil::getEnv();
|
||||
const int srcLen = srcEnd - srcStart;
|
||||
if (srcLen > myBufferLength) {
|
||||
delete[] myCppOutBuffer;
|
||||
env->DeleteLocalRef(myOutBuffer);
|
||||
env->DeleteLocalRef(myInBuffer);
|
||||
myBufferLength = srcLen;
|
||||
myInBuffer = env->NewByteArray(myBufferLength);
|
||||
myOutBuffer = env->NewByteArray(2 * myBufferLength);
|
||||
myOutBuffer = env->NewCharArray(myBufferLength);
|
||||
myCppOutBuffer = new jchar[myBufferLength];
|
||||
}
|
||||
|
||||
env->SetByteArrayRegion(myInBuffer, 0, srcLen, (jbyte*)srcStart);
|
||||
const jint dstLen = AndroidUtil::Method_EncodingConverter_convert->call(myJavaConverter, myInBuffer, 0, srcLen, myOutBuffer, 0);
|
||||
const int origLen = dst.size();
|
||||
dst.append(dstLen, '\0');
|
||||
env->GetByteArrayRegion(myOutBuffer, 0, dstLen, (jbyte*)dst.data() + origLen);
|
||||
const jint decodedCount = AndroidUtil::Method_EncodingConverter_convert->call(
|
||||
myJavaConverter, myInBuffer, 0, srcLen, myOutBuffer
|
||||
);
|
||||
dst.reserve(dst.length() + decodedCount * 3);
|
||||
env->GetCharArrayRegion(myOutBuffer, 0, decodedCount, myCppOutBuffer);
|
||||
const jchar *end = myCppOutBuffer + decodedCount;
|
||||
char buffer[3];
|
||||
for (const jchar *ptr = myCppOutBuffer; ptr < end; ++ptr) {
|
||||
dst.append(buffer, ZLUnicodeUtil::ucs2ToUtf8(buffer, *ptr));
|
||||
}
|
||||
}
|
||||
|
||||
void JavaEncodingConverter::reset() {
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
-keep class org.geometerplus.zlibrary.core.encodings.EncodingConverter
|
||||
-keepclassmembers class org.geometerplus.zlibrary.core.encodings.EncodingConverter {
|
||||
public ** Name;
|
||||
public int convert(byte[],int,int,byte[],int);
|
||||
public int convert(byte[],int,int,char[]);
|
||||
public void reset();
|
||||
}
|
||||
-keep class org.geometerplus.zlibrary.core.encodings.JavaEncodingCollection
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
# project structure.
|
||||
|
||||
java.encoding=utf-8
|
||||
#proguard.config=proguard.cfg
|
||||
proguard.config=proguard.cfg
|
||||
# Project target.
|
||||
target=android-8
|
||||
|
|
|
@ -25,32 +25,24 @@ import java.nio.charset.*;
|
|||
public class EncodingConverter {
|
||||
public final String Name;
|
||||
private CharsetDecoder myDecoder;
|
||||
private CharsetEncoder myEncoder;
|
||||
|
||||
EncodingConverter(String encoding) {
|
||||
Name = encoding;
|
||||
myDecoder = Charset.forName(encoding).newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
myEncoder = Charset.forName("utf-8").newEncoder();
|
||||
}
|
||||
|
||||
// we assume out is large enough for this conversion
|
||||
// returns number of filled bytes in out buffer
|
||||
public int convert(byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
|
||||
// returns number of filled chars in out buffer
|
||||
public int convert(byte[] in, int inOffset, int inLength, char[] out) {
|
||||
final ByteBuffer inBuffer = ByteBuffer.wrap(in, inOffset, inLength);
|
||||
final ByteBuffer outBuffer = ByteBuffer.wrap(out, outOffset, out.length - outOffset);
|
||||
try {
|
||||
final CharBuffer charBuffer = myDecoder.decode(inBuffer);
|
||||
myEncoder.encode(charBuffer, outBuffer, true);
|
||||
} catch (CharacterCodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
final CharBuffer outBuffer = CharBuffer.wrap(out, 0, out.length);
|
||||
myDecoder.decode(inBuffer, outBuffer, false);
|
||||
return outBuffer.position();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
myDecoder.reset();
|
||||
myEncoder.reset();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue