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