jdk/src/java.base/share/native/libjava/jni_util.c
changeset 45572 07f412070bd9
parent 42442 0e6009a5b092
equal deleted inserted replaced
45571:a905332da8c6 45572:07f412070bd9
    27 #include <string.h>
    27 #include <string.h>
    28 
    28 
    29 #include "jvm.h"
    29 #include "jvm.h"
    30 #include "jni.h"
    30 #include "jni.h"
    31 #include "jni_util.h"
    31 #include "jni_util.h"
       
    32 #include "java_lang_String.h"
    32 
    33 
    33 /* Due to a bug in the win32 C runtime library strings
    34 /* Due to a bug in the win32 C runtime library strings
    34  * such as "z:" need to be appended with a "." so we
    35  * such as "z:" need to be appended with a "." so we
    35  * must allocate at least 4 bytes to allow room for
    36  * must allocate at least 4 bytes to allow room for
    36  * this expansion. See 4235353 for details.
    37  * this expansion. See 4235353 for details.
   440  done:
   441  done:
   441     (*env)->DeleteLocalRef(env, cls);
   442     (*env)->DeleteLocalRef(env, cls);
   442     return obj;
   443     return obj;
   443 }
   444 }
   444 
   445 
   445 /* Optimized for char set ISO_8559_1 */
   446 /* Optimized for charset ISO_8559_1 */
   446 static jstring
   447 static jstring
   447 newString8859_1(JNIEnv *env, const char *str)
   448 newSizedString8859_1(JNIEnv *env, const char *str, const int len)
   448 {
   449 {
   449     int len = (int)strlen(str);
       
   450     jchar buf[512];
   450     jchar buf[512];
   451     jchar *str1;
   451     jchar *str1;
   452     jstring result;
   452     jstring result;
   453     int i;
   453     int i;
       
   454 
       
   455     if ((*env)->EnsureLocalCapacity(env, 1) < 0)
       
   456         return NULL;
   454 
   457 
   455     if (len > 512) {
   458     if (len > 512) {
   456         str1 = (jchar *)malloc(len * sizeof(jchar));
   459         str1 = (jchar *)malloc(len * sizeof(jchar));
   457         if (str1 == 0) {
   460         if (str1 == 0) {
   458             JNU_ThrowOutOfMemoryError(env, 0);
   461             JNU_ThrowOutOfMemoryError(env, 0);
   467     if (str1 != buf)
   470     if (str1 != buf)
   468         free(str1);
   471         free(str1);
   469     return result;
   472     return result;
   470 }
   473 }
   471 
   474 
       
   475 static jstring
       
   476 newString8859_1(JNIEnv *env, const char *str)
       
   477 {
       
   478     int len = (int)strlen(str);
       
   479     return newSizedString8859_1(env, str, len);
       
   480 }
       
   481 
   472 static const char*
   482 static const char*
   473 getString8859_1Chars(JNIEnv *env, jstring jstr)
   483 getString8859_1Chars(JNIEnv *env, jstring jstr)
   474 {
   484 {
   475     int i;
   485     int i;
   476     char *result;
   486     char *result;
   499     (*env)->ReleaseStringCritical(env, jstr, str);
   509     (*env)->ReleaseStringCritical(env, jstr, str);
   500     return result;
   510     return result;
   501 }
   511 }
   502 
   512 
   503 
   513 
   504 /* Optimized for char set ISO646-US (us-ascii) */
   514 /* Optimized for charset ISO646-US (us-ascii) */
   505 static jstring
   515 static jstring
   506 newString646_US(JNIEnv *env, const char *str)
   516 newString646_US(JNIEnv *env, const char *str)
   507 {
   517 {
   508     int len = (int)strlen(str);
   518     int len = (int)strlen(str);
   509     jchar buf[512];
   519     jchar buf[512];
   571     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
   581     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
   572     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
   582     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
   573     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
   583     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
   574 };
   584 };
   575 
   585 
   576 /* Optimized for char set Cp1252 */
   586 /* Optimized for charset Cp1252 */
   577 static jstring
   587 static jstring
   578 newStringCp1252(JNIEnv *env, const char *str)
   588 newStringCp1252(JNIEnv *env, const char *str)
   579 {
   589 {
   580     int len = (int) strlen(str);
   590     int len = (int) strlen(str);
   581     jchar buf[512];
   591     jchar buf[512];
   582     jchar *str1;
   592     jchar *str1;
   583     jstring result;
   593     jstring result;
   584     int i;
   594     int i;
       
   595 
       
   596     if ((*env)->EnsureLocalCapacity(env, 1) < 0)
       
   597         return NULL;
       
   598 
   585     if (len > 512) {
   599     if (len > 512) {
   586         str1 = (jchar *)malloc(len * sizeof(jchar));
   600         str1 = (jchar *)malloc(len * sizeof(jchar));
   587         if (str1 == 0) {
   601         if (str1 == 0) {
   588             JNU_ThrowOutOfMemoryError(env, 0);
   602             JNU_ThrowOutOfMemoryError(env, 0);
   589             return 0;
   603             return 0;
   623         return 0;
   637         return 0;
   624     }
   638     }
   625 
   639 
   626     for (i=0; i<len; i++) {
   640     for (i=0; i<len; i++) {
   627         jchar c = str[i];
   641         jchar c = str[i];
   628         if (c < 256)
   642         if (c < 256) {
   629             result[i] = (char)c;
   643             if ((c >= 0x80) && (c <= 0x9f)) {
   630         else switch(c) {
   644                 result[i] = '?';
       
   645             } else {
       
   646                 result[i] = (char)c;
       
   647             }
       
   648         } else switch(c) {
   631             case 0x20AC: result[i] = (char)0x80; break;
   649             case 0x20AC: result[i] = (char)0x80; break;
   632             case 0x201A: result[i] = (char)0x82; break;
   650             case 0x201A: result[i] = (char)0x82; break;
   633             case 0x0192: result[i] = (char)0x83; break;
   651             case 0x0192: result[i] = (char)0x83; break;
   634             case 0x201E: result[i] = (char)0x84; break;
   652             case 0x201E: result[i] = (char)0x84; break;
   635             case 0x2026: result[i] = (char)0x85; break;
   653             case 0x2026: result[i] = (char)0x85; break;
   669 
   687 
   670 /* Cached method IDs */
   688 /* Cached method IDs */
   671 static jmethodID String_init_ID;        /* String(byte[], enc) */
   689 static jmethodID String_init_ID;        /* String(byte[], enc) */
   672 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
   690 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
   673 
   691 
   674 int getFastEncoding() {
   692 /* Cached field IDs */
   675     return fastEncoding;
   693 static jfieldID String_coder_ID;        /* String.coder */
       
   694 static jfieldID String_value_ID;        /* String.value */
       
   695 
       
   696 static jboolean isJNUEncodingSupported = JNI_FALSE;
       
   697 static jboolean jnuEncodingSupported(JNIEnv *env) {
       
   698     jboolean exe;
       
   699     if (isJNUEncodingSupported == JNI_TRUE) {
       
   700         return JNI_TRUE;
       
   701     }
       
   702     isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
       
   703                                     env, &exe,
       
   704                                     "java/nio/charset/Charset",
       
   705                                     "isSupported",
       
   706                                     "(Ljava/lang/String;)Z",
       
   707                                     jnuEncoding).z;
       
   708     return isJNUEncodingSupported;
       
   709 }
       
   710 
       
   711 /* Create a new string by converting str to a heap-allocated byte array and
       
   712  * calling the appropriate String constructor.
       
   713  */
       
   714 static jstring
       
   715 newSizedStringJava(JNIEnv *env, const char *str, const int len)
       
   716 {
       
   717     jstring result = NULL;
       
   718     jbyteArray bytes = 0;
       
   719 
       
   720     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
       
   721         return NULL;
       
   722 
       
   723     bytes = (*env)->NewByteArray(env, len);
       
   724     if (bytes != NULL) {
       
   725         jclass strClazz = JNU_ClassString(env);
       
   726         CHECK_NULL_RETURN(strClazz, 0);
       
   727         (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
       
   728         if (jnuEncodingSupported(env)) {
       
   729             result = (*env)->NewObject(env, strClazz,
       
   730                                        String_init_ID, bytes, jnuEncoding);
       
   731         } else {
       
   732             /*If the encoding specified in sun.jnu.encoding is not endorsed
       
   733               by "Charset.isSupported" we have to fall back to use String(byte[])
       
   734               explicitly here without specifying the encoding name, in which the
       
   735               StringCoding class will pickup the iso-8859-1 as the fallback
       
   736               converter for us.
       
   737              */
       
   738             jmethodID mid = (*env)->GetMethodID(env, strClazz,
       
   739                                                 "<init>", "([B)V");
       
   740             if (mid != NULL) {
       
   741                 result = (*env)->NewObject(env, strClazz, mid, bytes);
       
   742             }
       
   743         }
       
   744         (*env)->DeleteLocalRef(env, bytes);
       
   745         return result;
       
   746     }
       
   747     return NULL;
       
   748 }
       
   749 
       
   750 static jstring
       
   751 newStringJava(JNIEnv *env, const char *str)
       
   752 {
       
   753     int len = (int)strlen(str);
       
   754     return newSizedStringJava(env, str, len);
       
   755 }
       
   756 
       
   757 /* Optimized for charset UTF-8 */
       
   758 static jstring
       
   759 newStringUTF8(JNIEnv *env, const char *str)
       
   760 {
       
   761     int len;
       
   762     const unsigned char *p;
       
   763     unsigned char asciiCheck;
       
   764     for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) {
       
   765         asciiCheck |= *p;
       
   766     }
       
   767     len = (int)((const char*)p - str);
       
   768 
       
   769     if (asciiCheck < 0x80) {
       
   770         // ascii fast-path
       
   771         return newSizedString8859_1(env, str, len);
       
   772     }
       
   773 
       
   774     return newSizedStringJava(env, str, len);
   676 }
   775 }
   677 
   776 
   678 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
   777 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
   679  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
   778  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
   680  */
   779  */
   716             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
   815             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
   717             */
   816             */
   718                     if ((strcmp(encname, "8859_1") == 0) ||
   817                     if ((strcmp(encname, "8859_1") == 0) ||
   719                         (strcmp(encname, "ISO8859-1") == 0) ||
   818                         (strcmp(encname, "ISO8859-1") == 0) ||
   720                         (strcmp(encname, "ISO8859_1") == 0) ||
   819                         (strcmp(encname, "ISO8859_1") == 0) ||
   721                         (strcmp(encname, "ISO-8859-1") == 0))
   820                         (strcmp(encname, "ISO-8859-1") == 0)) {
   722                         fastEncoding = FAST_8859_1;
   821                         fastEncoding = FAST_8859_1;
   723                     else if (strcmp(encname, "ISO646-US") == 0)
   822                     } else if (strcmp(encname, "UTF-8") == 0) {
       
   823                         fastEncoding = FAST_UTF_8;
       
   824                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
       
   825                     } else if (strcmp(encname, "ISO646-US") == 0) {
   724                         fastEncoding = FAST_646_US;
   826                         fastEncoding = FAST_646_US;
   725                     else if (strcmp(encname, "Cp1252") == 0 ||
   827                     } else if (strcmp(encname, "Cp1252") == 0 ||
   726                              /* This is a temporary fix until we move */
   828                              /* This is a temporary fix until we move */
   727                              /* to wide character versions of all Windows */
   829                              /* to wide character versions of all Windows */
   728                              /* calls. */
   830                              /* calls. */
   729                              strcmp(encname, "utf-16le") == 0)
   831                              strcmp(encname, "utf-16le") == 0) {
   730                         fastEncoding = FAST_CP1252;
   832                         fastEncoding = FAST_CP1252;
   731                     else {
   833                     } else {
   732                         fastEncoding = NO_FAST_ENCODING;
   834                         fastEncoding = NO_FAST_ENCODING;
   733                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
   835                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
   734                     }
   836                     }
   735                     (*env)->ReleaseStringUTFChars(env, enc, encname);
   837                     (*env)->ReleaseStringUTFChars(env, enc, encname);
   736                 }
   838                 }
   748     String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
   850     String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
   749                                              "getBytes", "(Ljava/lang/String;)[B");
   851                                              "getBytes", "(Ljava/lang/String;)[B");
   750     CHECK_NULL(String_getBytes_ID);
   852     CHECK_NULL(String_getBytes_ID);
   751     String_init_ID = (*env)->GetMethodID(env, strClazz,
   853     String_init_ID = (*env)->GetMethodID(env, strClazz,
   752                                          "<init>", "([BLjava/lang/String;)V");
   854                                          "<init>", "([BLjava/lang/String;)V");
   753 }
   855     String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
   754 
   856     String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B");
   755 static jboolean isJNUEncodingSupported = JNI_FALSE;
   857 }
   756 static jboolean jnuEncodingSupported(JNIEnv *env) {
       
   757     jboolean exe;
       
   758     if (isJNUEncodingSupported == JNI_TRUE) {
       
   759         return JNI_TRUE;
       
   760     }
       
   761     isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
       
   762                                     env, &exe,
       
   763                                     "java/nio/charset/Charset",
       
   764                                     "isSupported",
       
   765                                     "(Ljava/lang/String;)Z",
       
   766                                     jnuEncoding).z;
       
   767     return isJNUEncodingSupported;
       
   768 }
       
   769 
       
   770 
   858 
   771 JNIEXPORT jstring
   859 JNIEXPORT jstring
   772 NewStringPlatform(JNIEnv *env, const char *str)
   860 NewStringPlatform(JNIEnv *env, const char *str)
   773 {
   861 {
   774     return JNU_NewStringPlatform(env, str);
   862     return JNU_NewStringPlatform(env, str);
   775 }
   863 }
   776 
   864 
   777 JNIEXPORT jstring JNICALL
   865 JNIEXPORT jstring JNICALL
   778 JNU_NewStringPlatform(JNIEnv *env, const char *str)
   866 JNU_NewStringPlatform(JNIEnv *env, const char *str)
   779 {
   867 {
   780     jstring result = NULL;
       
   781     jbyteArray hab = 0;
       
   782     int len;
       
   783 
       
   784     if (fastEncoding == NO_ENCODING_YET) {
   868     if (fastEncoding == NO_ENCODING_YET) {
   785         initializeEncoding(env);
   869         initializeEncoding(env);
   786         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
   870         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
   787     }
   871     }
   788 
   872 
   790         return newString8859_1(env, str);
   874         return newString8859_1(env, str);
   791     if (fastEncoding == FAST_646_US)
   875     if (fastEncoding == FAST_646_US)
   792         return newString646_US(env, str);
   876         return newString646_US(env, str);
   793     if (fastEncoding == FAST_CP1252)
   877     if (fastEncoding == FAST_CP1252)
   794         return newStringCp1252(env, str);
   878         return newStringCp1252(env, str);
   795 
   879     if (fastEncoding == FAST_UTF_8)
   796     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
   880         return newStringUTF8(env, str);
   797         return NULL;
   881     return newStringJava(env, str);
   798 
       
   799     len = (int)strlen(str);
       
   800     hab = (*env)->NewByteArray(env, len);
       
   801     if (hab != 0) {
       
   802         jclass strClazz = JNU_ClassString(env);
       
   803         CHECK_NULL_RETURN(strClazz, 0);
       
   804         (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
       
   805         if (jnuEncodingSupported(env)) {
       
   806             result = (*env)->NewObject(env, strClazz,
       
   807                                        String_init_ID, hab, jnuEncoding);
       
   808         } else {
       
   809             /*If the encoding specified in sun.jnu.encoding is not endorsed
       
   810               by "Charset.isSupported" we have to fall back to use String(byte[])
       
   811               explicitly here without specifying the encoding name, in which the
       
   812               StringCoding class will pickup the iso-8859-1 as the fallback
       
   813               converter for us.
       
   814              */
       
   815             jmethodID mid = (*env)->GetMethodID(env, strClazz,
       
   816                                                 "<init>", "([B)V");
       
   817             if (mid != NULL) {
       
   818                 result = (*env)->NewObject(env, strClazz, mid, hab);
       
   819             }
       
   820         }
       
   821         (*env)->DeleteLocalRef(env, hab);
       
   822         return result;
       
   823     }
       
   824     return NULL;
       
   825 }
   882 }
   826 
   883 
   827 JNIEXPORT const char *
   884 JNIEXPORT const char *
   828 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
   885 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
   829 {
   886 {
   830     return JNU_GetStringPlatformChars(env, jstr, isCopy);
   887     return JNU_GetStringPlatformChars(env, jstr, isCopy);
   831 }
   888 }
   832 
   889 
   833 JNIEXPORT const char * JNICALL
   890 static const char* getStringBytes(JNIEnv *env, jstring jstr) {
   834 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
       
   835 {
       
   836     char *result = NULL;
   891     char *result = NULL;
   837     jbyteArray hab = 0;
   892     jbyteArray hab = 0;
   838 
       
   839     if (isCopy)
       
   840         *isCopy = JNI_TRUE;
       
   841 
       
   842     if (fastEncoding == NO_ENCODING_YET) {
       
   843         initializeEncoding(env);
       
   844         JNU_CHECK_EXCEPTION_RETURN(env, 0);
       
   845     }
       
   846 
       
   847     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
       
   848         return getString8859_1Chars(env, jstr);
       
   849     if (fastEncoding == FAST_646_US)
       
   850         return getString646_USChars(env, jstr);
       
   851     if (fastEncoding == FAST_CP1252)
       
   852         return getStringCp1252Chars(env, jstr);
       
   853 
   893 
   854     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
   894     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
   855         return 0;
   895         return 0;
   856 
   896 
   857     if (jnuEncodingSupported(env)) {
   897     if (jnuEncodingSupported(env)) {
   881 
   921 
   882     (*env)->DeleteLocalRef(env, hab);
   922     (*env)->DeleteLocalRef(env, hab);
   883     return result;
   923     return result;
   884 }
   924 }
   885 
   925 
       
   926 static const char*
       
   927 getStringUTF8(JNIEnv *env, jstring jstr)
       
   928 {
       
   929     int i;
       
   930     char *result;
       
   931     jbyteArray value;
       
   932     jint len;
       
   933     jbyte *str;
       
   934     jint rlen;
       
   935     int ri;
       
   936     jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
       
   937     if (coder != java_lang_String_LATIN1) {
       
   938         return getStringBytes(env, jstr);
       
   939     }
       
   940     if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
       
   941         return NULL;
       
   942     }
       
   943     value = (*env)->GetObjectField(env, jstr, String_value_ID);
       
   944     if (value == NULL)
       
   945         return NULL;
       
   946     len = (*env)->GetArrayLength(env, value);
       
   947     str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
       
   948     if (str == NULL) {
       
   949         return NULL;
       
   950     }
       
   951 
       
   952     rlen = len;
       
   953     // we need two bytes for each latin-1 char above 127 (negative jbytes)
       
   954     for (i = 0; i < len; i++) {
       
   955         if (str[i] < 0) {
       
   956             rlen++;
       
   957         }
       
   958     }
       
   959 
       
   960     result = MALLOC_MIN4(rlen);
       
   961     if (result == NULL) {
       
   962         (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
       
   963         JNU_ThrowOutOfMemoryError(env, 0);
       
   964         return NULL;
       
   965     }
       
   966 
       
   967     for (ri = 0, i = 0; i < len; i++) {
       
   968         jbyte c = str[i];
       
   969         if (c < 0) {
       
   970             result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6));
       
   971             result[ri++] = (char)(0x80 | (c & 0x3f));
       
   972         } else {
       
   973             result[ri++] = c;
       
   974         }
       
   975     }
       
   976     (*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
       
   977     result[rlen] = '\0';
       
   978     return result;
       
   979 }
       
   980 
       
   981 JNIEXPORT const char * JNICALL
       
   982 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
       
   983 {
       
   984 
       
   985     if (isCopy)
       
   986         *isCopy = JNI_TRUE;
       
   987 
       
   988     if (fastEncoding == NO_ENCODING_YET) {
       
   989         initializeEncoding(env);
       
   990         JNU_CHECK_EXCEPTION_RETURN(env, 0);
       
   991     }
       
   992 
       
   993     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
       
   994         return getString8859_1Chars(env, jstr);
       
   995     if (fastEncoding == FAST_646_US)
       
   996         return getString646_USChars(env, jstr);
       
   997     if (fastEncoding == FAST_CP1252)
       
   998         return getStringCp1252Chars(env, jstr);
       
   999     if (fastEncoding == FAST_UTF_8)
       
  1000         return getStringUTF8(env, jstr);
       
  1001     else
       
  1002         return getStringBytes(env, jstr);
       
  1003 }
       
  1004 
   886 JNIEXPORT void JNICALL
  1005 JNIEXPORT void JNICALL
   887 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
  1006 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
   888 {
  1007 {
   889     free((void *)str);
  1008     free((void *)str);
   890 }
  1009 }