diff --git a/readme.md b/readme.md index 11bbefb..0ef6ca7 100755 --- a/readme.md +++ b/readme.md @@ -122,9 +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() * 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 b594450..c0de6a7 100755 --- a/src/main/cpp/generic.cpp +++ b/src/main/cpp/generic.cpp @@ -1,5 +1,5 @@ /* - * Generic functions + * Generic cross-platform functions. */ #include "native.h" #include "generic.h" diff --git a/src/main/cpp/linux.cpp b/src/main/cpp/linux.cpp index 2372d26..d0e1943 100644 --- a/src/main/cpp/linux.cpp +++ b/src/main/cpp/linux.cpp @@ -22,9 +22,9 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V"); while (getmntent_r(fp, &mount_info, buf, sizeof(buf)) != NULL) { - jstring mount_point = env->NewStringUTF(mount_info.mnt_dir); - jstring file_system_type = env->NewStringUTF(mount_info.mnt_type); - jstring device_name = env->NewStringUTF(mount_info.mnt_fsname); + jstring mount_point = char_to_java(env, mount_info.mnt_dir, result); + jstring file_system_type = char_to_java(env, mount_info.mnt_type, result); + jstring device_name = char_to_java(env, mount_info.mnt_fsname, result); env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, JNI_FALSE); } diff --git a/src/main/cpp/osx.cpp b/src/main/cpp/osx.cpp index 31ae0b1..5bee896 100644 --- a/src/main/cpp/osx.cpp +++ b/src/main/cpp/osx.cpp @@ -30,9 +30,9 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V"); for (int i = 0; i < fs_count; i++) { - jstring mount_point = env->NewStringUTF(buf[i].f_mntonname); - jstring file_system_type = env->NewStringUTF(buf[i].f_fstypename); - jstring device_name = env->NewStringUTF(buf[i].f_mntfromname); + jstring mount_point = char_to_java(env, buf[i].f_mntonname, result); + jstring file_system_type = char_to_java(env, buf[i].f_fstypename, result); + jstring device_name = char_to_java(env, buf[i].f_mntfromname, result); jboolean remote = (buf[i].f_flags & MNT_LOCAL) == 0; env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, remote); } diff --git a/src/main/cpp/posix.cpp b/src/main/cpp/posix.cpp index 30d18af..41f6013 100755 --- a/src/main/cpp/posix.cpp +++ b/src/main/cpp/posix.cpp @@ -14,6 +14,7 @@ #include #include #include +#include /* * Marks the given result as failed, using the current value of errno @@ -22,6 +23,24 @@ void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) { mark_failed_with_code(env, message, errno, result); } +char_str* java_to_char_str(JNIEnv *env, jstring string, jobject result) { + return NULL; +} + +void char_str_free(char_str* str) { +} + +jstring char_to_java(JNIEnv* env, const char* chars, jobject result) { + 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); +} + JNIEXPORT void JNICALL Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) { jclass infoClass = env->GetObjectClass(info); @@ -44,11 +63,11 @@ Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemIn } jfieldID osNameField = env->GetFieldID(infoClass, "osName", "Ljava/lang/String;"); - env->SetObjectField(info, osNameField, env->NewStringUTF(machine_info.sysname)); + env->SetObjectField(info, osNameField, char_to_java(env, machine_info.sysname, result)); jfieldID osVersionField = env->GetFieldID(infoClass, "osVersion", "Ljava/lang/String;"); - env->SetObjectField(info, osVersionField, env->NewStringUTF(machine_info.release)); + env->SetObjectField(info, osVersionField, char_to_java(env, machine_info.release, result)); jfieldID machineArchitectureField = env->GetFieldID(infoClass, "machineArchitecture", "Ljava/lang/String;"); - env->SetObjectField(info, machineArchitectureField, env->NewStringUTF(machine_info.machine)); + env->SetObjectField(info, machineArchitectureField, char_to_java(env, machine_info.machine, result)); } /* @@ -247,7 +266,7 @@ Java_net_rubygrapefruit_platform_internal_jni_TerminfoFunctions_initTerminal(JNI jclass destClass = env->GetObjectClass(capabilities); jfieldID field = env->GetFieldID(destClass, "terminalName", "Ljava/lang/String;"); - jstring jtermType = env->NewStringUTF(termType); + jstring jtermType = char_to_java(env, termType, result); env->SetObjectField(capabilities, field, jtermType); // Text attributes diff --git a/src/main/headers/generic.h b/src/main/headers/generic.h index 6d8edb1..eb6d03d 100755 --- a/src/main/headers/generic.h +++ b/src/main/headers/generic.h @@ -22,6 +22,63 @@ extern void mark_failed_with_errno(JNIEnv *env, const char* message, jobject res */ extern void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, jobject result); +typedef struct wchar_struct { + // Not NULL terminated + wchar_t* chars; + // number of characters in the string + size_t len; + jstring source; + JNIEnv *env; +} wchar_str; + +/* + * Converts the given Java string to a wchar_str. Should call wchar_str_free() when finished. + * + * Returns NULL on failure. + */ +extern wchar_str* +java_to_wchar_str(JNIEnv *env, jstring string, jobject result); + +/* + * Releases resources used by the given string. + */ +extern void wchar_str_free(wchar_str* str); + +/* + * Converts the given wchar_t string to a Java string. + * + * Returns NULL on failure. + */ +extern jstring wchar_to_java(JNIEnv* env, const wchar_t* chars, size_t len, jobject result); + +typedef struct char_struct { + // NULL terminated + char* chars; + // Number of chars in the string, excluding the NULL terminator + size_t len; + jstring source; + JNIEnv *env; +} char_str; + +/* + * Converts the given Java string to a char_str. Should call char_str_free() when finished. + * + * Returns NULL on failure. + */ +extern char_str* java_to_char_str(JNIEnv *env, jstring string, jobject result); + +/* + * Releases resources used by the given string. + */ +extern void char_str_free(char_str* str); + +/* + * Converts the given NULL terminated char string to a Java string. + * + * Returns NULL on failure. + */ +extern jstring char_to_java(JNIEnv* env, const char* chars, jobject result); + #ifdef __cplusplus } #endif