From 7e2a573ff210f13a3a252cd63ddac530ef2c08ca Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Sun, 9 Sep 2012 10:22:40 +1000 Subject: [PATCH] - Changed char_to_java() to use C charset instead of JVM's default encoding. - Changed PosixFileFunctions.readLink() to return String instead of byte[]. --- readme.md | 2 +- src/main/cpp/generic.cpp | 2 +- src/main/cpp/posix.cpp | 28 +++++++++++++------ .../platform/internal/DefaultPosixFile.java | 12 ++------ .../internal/jni/NativeLibraryFunctions.java | 2 +- .../internal/jni/PosixFileFunctions.java | 2 +- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/readme.md b/readme.md index 0ef6ca7..3f05f23 100755 --- a/readme.md +++ b/readme.md @@ -122,11 +122,11 @@ You can run `$INSTALL_DIR/bin/native-platform` to run the test application. * Freebsd: finish port. * Freebsd: fail for unsupported architecture. * Freebsd: build 32 bit and 64 bit libraries. -* Unix: char_to_java() should use libc charset instead of java file.encoding ### Improvements * Implement java_to_char_str() +* Use iconv() to convert from C char string to UTF-16 when converting from C char string to Java String. * Support for cygwin terminal * Use TERM=xtermc instead of TERM=xterm on Solaris. * Add diagnostics for terminal. diff --git a/src/main/cpp/generic.cpp b/src/main/cpp/generic.cpp index c0de6a7..74d8d04 100755 --- a/src/main/cpp/generic.cpp +++ b/src/main/cpp/generic.cpp @@ -17,5 +17,5 @@ void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, job JNIEXPORT jint JNICALL Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) { - return 7; + return 8; } diff --git a/src/main/cpp/posix.cpp b/src/main/cpp/posix.cpp index 41f6013..bff0379 100755 --- a/src/main/cpp/posix.cpp +++ b/src/main/cpp/posix.cpp @@ -31,14 +31,23 @@ void char_str_free(char_str* str) { } jstring char_to_java(JNIEnv* env, const char* chars, jobject result) { + // TODO - share this code with nnn_getSystemInfo() below + locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL); + if (locale == NULL) { + mark_failed_with_message(env, "could not create locale", result); + return NULL; + } + jstring encoding = env->NewStringUTF(nl_langinfo_l(CODESET, locale)); + freelocale(locale); + size_t len = strlen(chars); jbyteArray byteArray = env->NewByteArray(len); jbyte* bytes = env->GetByteArrayElements(byteArray, NULL); memcpy(bytes, chars, len); env->ReleaseByteArrayElements(byteArray, bytes, JNI_COMMIT); jclass strClass = env->FindClass("java/lang/String"); - jmethodID method = env->GetMethodID(strClass, "", "([B)V"); - return (jstring)env->NewObject(strClass, method, byteArray); + jmethodID method = env->GetMethodID(strClass, "", "([BLjava/lang/String;)V"); + return (jstring)env->NewObject(strClass, method, byteArray, encoding); } JNIEXPORT void JNICALL @@ -111,7 +120,7 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv } } -JNIEXPORT jbyteArray JNICALL +JNIEXPORT jstring JNICALL Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jbyteArray path, jobject result) { struct stat link_info; jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL); @@ -122,23 +131,24 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv return NULL; } - jbyteArray contents = env->NewByteArray(link_info.st_size); + char* contents = (char*)malloc(link_info.st_size + 1); if (contents == NULL) { env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); mark_failed_with_message(env, "could not create array", result); return NULL; } - jbyte* contentsUtf8 = env->GetByteArrayElements(contents, NULL); - retval = readlink((const char*)pathUtf8, (char*)contentsUtf8, link_info.st_size); + retval = readlink((const char*)pathUtf8, contents, link_info.st_size); env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); if (retval < 0) { + free(contents); mark_failed_with_errno(env, "could not readlink", result); - env->ReleaseByteArrayElements(contents, contentsUtf8, JNI_ABORT); return NULL; } - env->ReleaseByteArrayElements(contents, contentsUtf8, JNI_COMMIT); - return contents; + contents[link_info.st_size] = 0; + jstring contents_str = char_to_java(env, contents, result); + free(contents); + return contents_str; } /* diff --git a/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java b/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java index ba2a47b..4ef6be1 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java @@ -36,11 +36,11 @@ public class DefaultPosixFile implements PosixFile { @Override public String readLink(File link) throws NativeException { FunctionResult result = new FunctionResult(); - byte[] encodedContents = PosixFileFunctions.readlink(encode(link), result); + String contents = PosixFileFunctions.readlink(encode(link), result); if (result.isFailed()) { throw new NativeException(String.format("Could not read symlink %s: %s", link, result.getMessage())); } - return decode(encodedContents); + return contents; } @Override @@ -52,14 +52,6 @@ public class DefaultPosixFile implements PosixFile { } } - private String decode(byte[] path) { - try { - return new String(path, 0, path.length, characterEncoding); - } catch (UnsupportedEncodingException e) { - throw new NativeException(String.format("Could not decode path using encoding %s.", characterEncoding), e); - } - } - private byte[] encode(File file) { return encode(file.getPath()); } diff --git a/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java b/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java index b5310a0..3ffed44 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java @@ -4,7 +4,7 @@ import net.rubygrapefruit.platform.internal.FunctionResult; import net.rubygrapefruit.platform.internal.MutableSystemInfo; public class NativeLibraryFunctions { - public static final int VERSION = 7; + public static final int VERSION = 8; public static native int getVersion(); diff --git a/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java b/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java index 4acf530..c8a1c47 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java @@ -10,5 +10,5 @@ public class PosixFileFunctions { public static native void symlink(byte[] file, byte[] content, FunctionResult result); - public static native byte[] readlink(byte[] file, FunctionResult result); + public static native String readlink(byte[] file, FunctionResult result); }