< prev index next >

src/java.base/share/native/libjava/jni_util.c

Print this page
rev 17266 : 8181147: JNI_GetStringPlatformChars should have a fast path for UTF-8
Reviewed-by: martin, erikj, chegar


 425         goto done;
 426 
 427     cls = (*env)->FindClass(env, class_name);
 428     if (cls == 0) {
 429         goto done;
 430     }
 431     cls_initMID  = (*env)->GetMethodID(env, cls,
 432                                        "<init>", constructor_sig);
 433     if (cls_initMID == NULL) {
 434         goto done;
 435     }
 436     va_start(args, constructor_sig);
 437     obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
 438     va_end(args);
 439 
 440  done:
 441     (*env)->DeleteLocalRef(env, cls);
 442     return obj;
 443 }
 444 
 445 /* Optimized for char set ISO_8559_1 */
 446 static jstring
 447 newString8859_1(JNIEnv *env, const char *str)
 448 {
 449     int len = (int)strlen(str);
 450     jchar buf[512];
 451     jchar *str1;
 452     jstring result;
 453     int i;
 454 
 455     if (len > 512) {
 456         str1 = (jchar *)malloc(len * sizeof(jchar));
 457         if (str1 == 0) {
 458             JNU_ThrowOutOfMemoryError(env, 0);
 459             return 0;
 460         }
 461     } else
 462         str1 = buf;
 463 
 464     for (i=0;i<len;i++)
 465         str1[i] = (unsigned char)str[i];
 466     result = (*env)->NewString(env, str1, len);
 467     if (str1 != buf)
 468         free(str1);
 469     return result;
 470 }
 471 










 472 static const char*
 473 getString8859_1Chars(JNIEnv *env, jstring jstr)
 474 {
 475     int i;
 476     char *result;
 477     jint len = (*env)->GetStringLength(env, jstr);
 478     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
 479     if (str == 0) {
 480         return 0;
 481     }
 482 
 483     result = MALLOC_MIN4(len);
 484     if (result == 0) {
 485         (*env)->ReleaseStringCritical(env, jstr, str);
 486         JNU_ThrowOutOfMemoryError(env, 0);
 487         return 0;
 488     }
 489 
 490     for (i=0; i<len; i++) {
 491         jchar unicode = str[i];
 492         if (unicode <= 0x00ff)
 493             result[i] = (char)unicode;
 494         else
 495             result[i] = '?';
 496     }
 497 
 498     result[len] = 0;
 499     (*env)->ReleaseStringCritical(env, jstr, str);
 500     return result;
 501 }
 502 
 503 
 504 /* Optimized for char set ISO646-US (us-ascii) */
 505 static jstring
 506 newString646_US(JNIEnv *env, const char *str)
 507 {
 508     int len = (int)strlen(str);
 509     jchar buf[512];
 510     jchar *str1;
 511     jstring result;
 512     int i;
 513 
 514     if (len > 512) {
 515         str1 = (jchar *)malloc(len * sizeof(jchar));
 516         if (str1 == 0) {
 517             JNU_ThrowOutOfMemoryError(env, 0);
 518             return 0;
 519         }
 520     } else
 521         str1 = buf;
 522 
 523     for (i=0; i<len; i++) {
 524         unsigned char c = (unsigned char)str[i];


 556         jchar unicode = str[i];
 557         if (unicode <= 0x007f )
 558             result[i] = (char)unicode;
 559         else
 560             result[i] = '?';
 561     }
 562 
 563     result[len] = 0;
 564     (*env)->ReleaseStringCritical(env, jstr, str);
 565     return result;
 566 }
 567 
 568 /* enumeration of c1 row from Cp1252 */
 569 static int cp1252c1chars[32] = {
 570     0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
 571     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
 572     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
 573     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
 574 };
 575 
 576 /* Optimized for char set Cp1252 */
 577 static jstring
 578 newStringCp1252(JNIEnv *env, const char *str)
 579 {
 580     int len = (int) strlen(str);
 581     jchar buf[512];
 582     jchar *str1;
 583     jstring result;
 584     int i;
 585     if (len > 512) {
 586         str1 = (jchar *)malloc(len * sizeof(jchar));
 587         if (str1 == 0) {
 588             JNU_ThrowOutOfMemoryError(env, 0);
 589             return 0;
 590         }
 591     } else
 592         str1 = buf;
 593 
 594     for (i=0; i<len; i++) {
 595         unsigned char c = (unsigned char)str[i];
 596         if ((c >= 0x80) && (c <= 0x9f))


 654             case 0x203A: result[i] = (char)0x9B; break;
 655             case 0x0153: result[i] = (char)0x9C; break;
 656             case 0x017E: result[i] = (char)0x9E; break;
 657             case 0x0178: result[i] = (char)0x9F; break;
 658             default:     result[i] = '?';  break;
 659         }
 660     }
 661 
 662     result[len] = 0;
 663     (*env)->ReleaseStringCritical(env, jstr, str);
 664     return result;
 665 }
 666 
 667 static int fastEncoding = NO_ENCODING_YET;
 668 static jstring jnuEncoding = NULL;
 669 
 670 /* Cached method IDs */
 671 static jmethodID String_init_ID;        /* String(byte[], enc) */
 672 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
 673 
 674 int getFastEncoding() {
 675     return fastEncoding;

















































































 676 }
 677 
 678 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
 679  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
 680  */
 681 void
 682 initializeEncoding(JNIEnv *env)
 683 {
 684     jstring propname = 0;
 685     jstring enc = 0;
 686     jclass strClazz = NULL;
 687 
 688     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
 689         return;
 690 
 691     strClazz = JNU_ClassString(env);
 692     CHECK_NULL(strClazz);
 693 
 694     propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
 695     if (propname) {


 701                         "getProperty",
 702                         "(Ljava/lang/String;)Ljava/lang/String;",
 703                         propname).l;
 704         if (!exc) {
 705             if (enc) {
 706                 const char* encname = (*env)->GetStringUTFChars(env, enc, 0);
 707                 if (encname) {
 708            /*
 709             * On Solaris with nl_langinfo() called in GetJavaProperties():
 710             *
 711             *   locale undefined -> NULL -> hardcoded default
 712             *   "C" locale       -> "" -> hardcoded default     (on 2.6)
 713             *   "C" locale       -> "ISO646-US"                 (on Sol 7/8)
 714             *   "en_US" locale -> "ISO8859-1"
 715             *   "en_GB" locale -> "ISO8859-1"                   (on Sol 7/8)
 716             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
 717             */
 718                     if ((strcmp(encname, "8859_1") == 0) ||
 719                         (strcmp(encname, "ISO8859-1") == 0) ||
 720                         (strcmp(encname, "ISO8859_1") == 0) ||
 721                         (strcmp(encname, "ISO-8859-1") == 0))
 722                         fastEncoding = FAST_8859_1;
 723                     else if (strcmp(encname, "ISO646-US") == 0)



 724                         fastEncoding = FAST_646_US;
 725                     else if (strcmp(encname, "Cp1252") == 0 ||
 726                              /* This is a temporary fix until we move */
 727                              /* to wide character versions of all Windows */
 728                              /* calls. */
 729                              strcmp(encname, "utf-16le") == 0)
 730                         fastEncoding = FAST_CP1252;
 731                     else {
 732                         fastEncoding = NO_FAST_ENCODING;
 733                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
 734                     }
 735                     (*env)->ReleaseStringUTFChars(env, enc, encname);
 736                 }
 737             }
 738         } else {
 739             (*env)->ExceptionClear(env);
 740         }
 741     } else {
 742         (*env)->ExceptionClear(env);
 743     }
 744     (*env)->DeleteLocalRef(env, propname);
 745     (*env)->DeleteLocalRef(env, enc);
 746 
 747     /* Initialize method-id cache */
 748     String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
 749                                              "getBytes", "(Ljava/lang/String;)[B");
 750     CHECK_NULL(String_getBytes_ID);
 751     String_init_ID = (*env)->GetMethodID(env, strClazz,
 752                                          "<init>", "([BLjava/lang/String;)V");


 753 }
 754 
 755 static jboolean isJNUEncodingSupported = JNI_FALSE;
 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 
 771 JNIEXPORT jstring
 772 NewStringPlatform(JNIEnv *env, const char *str)
 773 {
 774     return JNU_NewStringPlatform(env, str);
 775 }
 776 
 777 JNIEXPORT jstring JNICALL
 778 JNU_NewStringPlatform(JNIEnv *env, const char *str)
 779 {
 780     jstring result = NULL;
 781     jbyteArray hab = 0;
 782     int len;
 783 
 784     if (fastEncoding == NO_ENCODING_YET) {
 785         initializeEncoding(env);
 786         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 787     }
 788 
 789     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 790         return newString8859_1(env, str);
 791     if (fastEncoding == FAST_646_US)
 792         return newString646_US(env, str);
 793     if (fastEncoding == FAST_CP1252)
 794         return newStringCp1252(env, str);
 795 
 796     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 797         return NULL;
 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 }
 826 
 827 JNIEXPORT const char *
 828 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 829 {
 830     return JNU_GetStringPlatformChars(env, jstr, isCopy);
 831 }
 832 
 833 JNIEXPORT const char * JNICALL
 834 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 835 {
 836     char *result = NULL;
 837     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 
 854     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 855         return 0;
 856 
 857     if (jnuEncodingSupported(env)) {
 858         hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
 859     } else {
 860         jmethodID mid;
 861         jclass strClazz = JNU_ClassString(env);
 862         CHECK_NULL_RETURN(strClazz, 0);
 863         mid = (*env)->GetMethodID(env, strClazz,
 864                                        "getBytes", "()[B");
 865         if (mid != NULL) {
 866             hab = (*env)->CallObjectMethod(env, jstr, mid);
 867         }
 868     }
 869 
 870     if (!(*env)->ExceptionCheck(env)) {
 871         jint len = (*env)->GetArrayLength(env, hab);
 872         result = MALLOC_MIN4(len);
 873         if (result == 0) {
 874             JNU_ThrowOutOfMemoryError(env, 0);
 875             (*env)->DeleteLocalRef(env, hab);
 876             return 0;
 877         }
 878         (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
 879         result[len] = 0; /* NULL-terminate */
 880     }
 881 
 882     (*env)->DeleteLocalRef(env, hab);
 883     return result;
 884 }
 885 










































































 886 JNIEXPORT void JNICALL
 887 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
 888 {
 889     free((void *)str);
 890 }
 891 
 892 /*
 893  * Export the platform dependent path canonicalization so that
 894  * VM can find it when loading system classes.
 895  * This function is also used by the instrumentation agent.
 896  */
 897 extern int canonicalize(char *path, const char *out, int len);
 898 
 899 JNIEXPORT int
 900 Canonicalize(JNIEnv *unused, char *orig, char *out, int len)
 901 {
 902     /* canonicalize an already natived path */
 903     return canonicalize(orig, out, len);
 904 }
 905 




 425         goto done;
 426 
 427     cls = (*env)->FindClass(env, class_name);
 428     if (cls == 0) {
 429         goto done;
 430     }
 431     cls_initMID  = (*env)->GetMethodID(env, cls,
 432                                        "<init>", constructor_sig);
 433     if (cls_initMID == NULL) {
 434         goto done;
 435     }
 436     va_start(args, constructor_sig);
 437     obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
 438     va_end(args);
 439 
 440  done:
 441     (*env)->DeleteLocalRef(env, cls);
 442     return obj;
 443 }
 444 
 445 /* Optimized for charset ISO_8559_1 */
 446 static jstring
 447 newSizedString8859_1(JNIEnv *env, const char *str, const int len)
 448 {

 449     jchar buf[512];
 450     jchar *str1;
 451     jstring result;
 452     int i;
 453 
 454     if (len > 512) {
 455         str1 = (jchar *)malloc(len * sizeof(jchar));
 456         if (str1 == 0) {
 457             JNU_ThrowOutOfMemoryError(env, 0);
 458             return 0;
 459         }
 460     } else
 461         str1 = buf;
 462 
 463     for (i=0;i<len;i++)
 464         str1[i] = (unsigned char)str[i];
 465     result = (*env)->NewString(env, str1, len);
 466     if (str1 != buf)
 467         free(str1);
 468     return result;
 469 }
 470 
 471 static jstring
 472 newString8859_1(JNIEnv *env, const char *str)
 473 {
 474     int len = (int)strlen(str);
 475     return newSizedString8859_1(env, str, len);
 476 }
 477 
 478 static const jbyte LATIN1 = 0;
 479 static const jbyte UTF16  = 1;
 480 
 481 static const char*
 482 getString8859_1Chars(JNIEnv *env, jstring jstr)
 483 {
 484     int i;
 485     char *result;
 486     jint len = (*env)->GetStringLength(env, jstr);
 487     const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
 488     if (str == 0) {
 489         return 0;
 490     }
 491 
 492     result = MALLOC_MIN4(len);
 493     if (result == 0) {
 494         (*env)->ReleaseStringCritical(env, jstr, str);
 495         JNU_ThrowOutOfMemoryError(env, 0);
 496         return 0;
 497     }
 498 
 499     for (i=0; i<len; i++) {
 500         jchar unicode = str[i];
 501         if (unicode <= 0x00ff)
 502             result[i] = (char)unicode;
 503         else
 504             result[i] = '?';
 505     }
 506 
 507     result[len] = 0;
 508     (*env)->ReleaseStringCritical(env, jstr, str);
 509     return result;
 510 }
 511 
 512 
 513 /* Optimized for charset ISO646-US (us-ascii) */
 514 static jstring
 515 newString646_US(JNIEnv *env, const char *str)
 516 {
 517     int len = (int)strlen(str);
 518     jchar buf[512];
 519     jchar *str1;
 520     jstring result;
 521     int i;
 522 
 523     if (len > 512) {
 524         str1 = (jchar *)malloc(len * sizeof(jchar));
 525         if (str1 == 0) {
 526             JNU_ThrowOutOfMemoryError(env, 0);
 527             return 0;
 528         }
 529     } else
 530         str1 = buf;
 531 
 532     for (i=0; i<len; i++) {
 533         unsigned char c = (unsigned char)str[i];


 565         jchar unicode = str[i];
 566         if (unicode <= 0x007f )
 567             result[i] = (char)unicode;
 568         else
 569             result[i] = '?';
 570     }
 571 
 572     result[len] = 0;
 573     (*env)->ReleaseStringCritical(env, jstr, str);
 574     return result;
 575 }
 576 
 577 /* enumeration of c1 row from Cp1252 */
 578 static int cp1252c1chars[32] = {
 579     0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
 580     0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
 581     0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
 582     0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
 583 };
 584 
 585 /* Optimized for charset Cp1252 */
 586 static jstring
 587 newStringCp1252(JNIEnv *env, const char *str)
 588 {
 589     int len = (int) strlen(str);
 590     jchar buf[512];
 591     jchar *str1;
 592     jstring result;
 593     int i;
 594     if (len > 512) {
 595         str1 = (jchar *)malloc(len * sizeof(jchar));
 596         if (str1 == 0) {
 597             JNU_ThrowOutOfMemoryError(env, 0);
 598             return 0;
 599         }
 600     } else
 601         str1 = buf;
 602 
 603     for (i=0; i<len; i++) {
 604         unsigned char c = (unsigned char)str[i];
 605         if ((c >= 0x80) && (c <= 0x9f))


 663             case 0x203A: result[i] = (char)0x9B; break;
 664             case 0x0153: result[i] = (char)0x9C; break;
 665             case 0x017E: result[i] = (char)0x9E; break;
 666             case 0x0178: result[i] = (char)0x9F; break;
 667             default:     result[i] = '?';  break;
 668         }
 669     }
 670 
 671     result[len] = 0;
 672     (*env)->ReleaseStringCritical(env, jstr, str);
 673     return result;
 674 }
 675 
 676 static int fastEncoding = NO_ENCODING_YET;
 677 static jstring jnuEncoding = NULL;
 678 
 679 /* Cached method IDs */
 680 static jmethodID String_init_ID;        /* String(byte[], enc) */
 681 static jmethodID String_getBytes_ID;    /* String.getBytes(enc) */
 682 
 683 /* Cached field IDs */
 684 static jfieldID String_coder_ID;        /* String.coder */
 685 static jfieldID String_value_ID;        /* String.value */
 686 
 687 static jboolean isJNUEncodingSupported = JNI_FALSE;
 688 static jboolean jnuEncodingSupported(JNIEnv *env) {
 689     jboolean exe;
 690     if (isJNUEncodingSupported == JNI_TRUE) {
 691         return JNI_TRUE;
 692     }
 693     isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
 694                                     env, &exe,
 695                                     "java/nio/charset/Charset",
 696                                     "isSupported",
 697                                     "(Ljava/lang/String;)Z",
 698                                     jnuEncoding).z;
 699     return isJNUEncodingSupported;
 700 }
 701 
 702 /* Create a new string by converting str to a heap-allocated byte array and
 703  * calling the appropriate String constructor.
 704  */
 705 static jstring
 706 newSizedStringJava(JNIEnv *env, const char *str, const int len)
 707 {
 708     jstring result = NULL;
 709     jbyteArray bytes = 0;
 710 
 711     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 712         return NULL;
 713 
 714     bytes = (*env)->NewByteArray(env, len);
 715     if (bytes != NULL) {
 716         jclass strClazz = JNU_ClassString(env);
 717         CHECK_NULL_RETURN(strClazz, 0);
 718         (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
 719         if (jnuEncodingSupported(env)) {
 720             result = (*env)->NewObject(env, strClazz,
 721                                        String_init_ID, bytes, jnuEncoding);
 722         } else {
 723             /*If the encoding specified in sun.jnu.encoding is not endorsed
 724               by "Charset.isSupported" we have to fall back to use String(byte[])
 725               explicitly here without specifying the encoding name, in which the
 726               StringCoding class will pickup the iso-8859-1 as the fallback
 727               converter for us.
 728              */
 729             jmethodID mid = (*env)->GetMethodID(env, strClazz,
 730                                                 "<init>", "([B)V");
 731             if (mid != NULL) {
 732                 result = (*env)->NewObject(env, strClazz, mid, bytes);
 733             }
 734         }
 735         (*env)->DeleteLocalRef(env, bytes);
 736         return result;
 737     }
 738     return NULL;
 739 }
 740 
 741 static jstring
 742 newStringJava(JNIEnv *env, const char *str)
 743 {
 744     int len = (int)strlen(str);
 745     return newSizedStringJava(env, str, len);
 746 }
 747 
 748 /* Optimized for charset UTF-8 */
 749 static jstring
 750 newStringUTF8(JNIEnv *env, const char *str)
 751 {
 752     int len;
 753     const unsigned char *p;
 754     unsigned char asciiCheck;
 755     for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) {
 756         asciiCheck |= *p;
 757     }
 758     len = (int)((const char*)p - str);
 759 
 760     if (asciiCheck < 0x80) {
 761         // ascii fast-path
 762         return newSizedString8859_1(env, str, len);
 763     }
 764 
 765     return newSizedStringJava(env, str, len);
 766 }
 767 
 768 /* Initialize the fast encoding.  If the "sun.jnu.encoding" property
 769  * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
 770  */
 771 void
 772 initializeEncoding(JNIEnv *env)
 773 {
 774     jstring propname = 0;
 775     jstring enc = 0;
 776     jclass strClazz = NULL;
 777 
 778     if ((*env)->EnsureLocalCapacity(env, 3) < 0)
 779         return;
 780 
 781     strClazz = JNU_ClassString(env);
 782     CHECK_NULL(strClazz);
 783 
 784     propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
 785     if (propname) {


 791                         "getProperty",
 792                         "(Ljava/lang/String;)Ljava/lang/String;",
 793                         propname).l;
 794         if (!exc) {
 795             if (enc) {
 796                 const char* encname = (*env)->GetStringUTFChars(env, enc, 0);
 797                 if (encname) {
 798            /*
 799             * On Solaris with nl_langinfo() called in GetJavaProperties():
 800             *
 801             *   locale undefined -> NULL -> hardcoded default
 802             *   "C" locale       -> "" -> hardcoded default     (on 2.6)
 803             *   "C" locale       -> "ISO646-US"                 (on Sol 7/8)
 804             *   "en_US" locale -> "ISO8859-1"
 805             *   "en_GB" locale -> "ISO8859-1"                   (on Sol 7/8)
 806             *   "en_UK" locale -> "ISO8859-1"                   (on 2.6)
 807             */
 808                     if ((strcmp(encname, "8859_1") == 0) ||
 809                         (strcmp(encname, "ISO8859-1") == 0) ||
 810                         (strcmp(encname, "ISO8859_1") == 0) ||
 811                         (strcmp(encname, "ISO-8859-1") == 0)) {
 812                         fastEncoding = FAST_8859_1;
 813                     } else if (strcmp(encname, "UTF-8") == 0) {
 814                         fastEncoding = FAST_UTF_8;
 815                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
 816                     } else if (strcmp(encname, "ISO646-US") == 0) {
 817                         fastEncoding = FAST_646_US;
 818                     } else if (strcmp(encname, "Cp1252") == 0 ||
 819                              /* This is a temporary fix until we move */
 820                              /* to wide character versions of all Windows */
 821                              /* calls. */
 822                              strcmp(encname, "utf-16le") == 0) {
 823                         fastEncoding = FAST_CP1252;
 824                     } else {
 825                         fastEncoding = NO_FAST_ENCODING;
 826                         jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
 827                     }
 828                     (*env)->ReleaseStringUTFChars(env, enc, encname);
 829                 }
 830             }
 831         } else {
 832             (*env)->ExceptionClear(env);
 833         }
 834     } else {
 835         (*env)->ExceptionClear(env);
 836     }
 837     (*env)->DeleteLocalRef(env, propname);
 838     (*env)->DeleteLocalRef(env, enc);
 839 
 840     /* Initialize method-id cache */
 841     String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
 842                                              "getBytes", "(Ljava/lang/String;)[B");
 843     CHECK_NULL(String_getBytes_ID);
 844     String_init_ID = (*env)->GetMethodID(env, strClazz,
 845                                          "<init>", "([BLjava/lang/String;)V");
 846     String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
 847     String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B");
 848 }
 849 
















 850 JNIEXPORT jstring
 851 NewStringPlatform(JNIEnv *env, const char *str)
 852 {
 853     return JNU_NewStringPlatform(env, str);
 854 }
 855 
 856 JNIEXPORT jstring JNICALL
 857 JNU_NewStringPlatform(JNIEnv *env, const char *str)
 858 {




 859     if (fastEncoding == NO_ENCODING_YET) {
 860         initializeEncoding(env);
 861         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 862     }
 863 
 864     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 865         return newString8859_1(env, str);
 866     if (fastEncoding == FAST_646_US)
 867         return newString646_US(env, str);
 868     if (fastEncoding == FAST_CP1252)
 869         return newStringCp1252(env, str);
 870     if (fastEncoding == FAST_UTF_8)
 871         return newStringUTF8(env, str);
 872     return newStringJava(env, str);



























 873 }
 874 
 875 JNIEXPORT const char *
 876 GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 877 {
 878     return JNU_GetStringPlatformChars(env, jstr, isCopy);
 879 }
 880 
 881 static const char* getStringBytes(JNIEnv *env, jstring jstr) {


 882     char *result = NULL;
 883     jbyteArray hab = 0;
 884 















 885     if ((*env)->EnsureLocalCapacity(env, 2) < 0)
 886         return 0;
 887 
 888     if (jnuEncodingSupported(env)) {
 889         hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
 890     } else {
 891         jmethodID mid;
 892         jclass strClazz = JNU_ClassString(env);
 893         CHECK_NULL_RETURN(strClazz, 0);
 894         mid = (*env)->GetMethodID(env, strClazz,
 895                                        "getBytes", "()[B");
 896         if (mid != NULL) {
 897             hab = (*env)->CallObjectMethod(env, jstr, mid);
 898         }
 899     }
 900 
 901     if (!(*env)->ExceptionCheck(env)) {
 902         jint len = (*env)->GetArrayLength(env, hab);
 903         result = MALLOC_MIN4(len);
 904         if (result == 0) {
 905             JNU_ThrowOutOfMemoryError(env, 0);
 906             (*env)->DeleteLocalRef(env, hab);
 907             return 0;
 908         }
 909         (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
 910         result[len] = 0; /* NULL-terminate */
 911     }
 912 
 913     (*env)->DeleteLocalRef(env, hab);
 914     return result;
 915 }
 916 
 917 static const char*
 918 getStringUTF8(JNIEnv *env, jstring jstr)
 919 {
 920     int i;
 921     char *result;
 922     jarray value;
 923     jint len;
 924     const jbyte *str;
 925     jint rlen;
 926     int ri;
 927     jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
 928     if (coder != LATIN1) {
 929         return getStringBytes(env, jstr);
 930     }
 931     value = (jarray)(*env)->GetObjectField(env, jstr, String_value_ID);
 932     len = (*env)->GetArrayLength(env, value);
 933     str = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, value, NULL);
 934 
 935     if (str == NULL) {
 936         return NULL;
 937     }
 938 
 939     rlen = len;
 940     // we need two bytes for each latin-1 char above 127 (negative jbytes)
 941     for (i = 0; i < len; i++) {
 942         if (str[i] < 0) {
 943             rlen++;
 944         }
 945     }
 946 
 947     result = MALLOC_MIN4(rlen);
 948     if (result == NULL) {
 949         (*env)->ReleasePrimitiveArrayCritical(env, jstr, (void *)str, 0);
 950         JNU_ThrowOutOfMemoryError(env, 0);
 951         return NULL;
 952     }
 953 
 954     for (ri = 0, i = 0; i < len; i++) {
 955         jbyte c = str[i];
 956         if (c < 0) {
 957             result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6));
 958             result[ri++] = (char)(0x80 | (c & 0x3f));
 959         } else {
 960             result[ri++] = c;
 961         }
 962     }
 963     result[rlen] = '\0';
 964     (*env)->ReleasePrimitiveArrayCritical(env, jstr, (void *)str, 0);
 965     return result;
 966 }
 967 
 968 JNIEXPORT const char * JNICALL
 969 JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
 970 {
 971 
 972     if (isCopy)
 973         *isCopy = JNI_TRUE;
 974 
 975     if (fastEncoding == NO_ENCODING_YET) {
 976         initializeEncoding(env);
 977         JNU_CHECK_EXCEPTION_RETURN(env, 0);
 978     }
 979 
 980     if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
 981         return getString8859_1Chars(env, jstr);
 982     if (fastEncoding == FAST_646_US)
 983         return getString646_USChars(env, jstr);
 984     if (fastEncoding == FAST_CP1252)
 985         return getStringCp1252Chars(env, jstr);
 986     if (fastEncoding == FAST_UTF_8)
 987         return getStringUTF8(env, jstr);
 988     else
 989         return getStringBytes(env, jstr);
 990 }
 991 JNIEXPORT void JNICALL
 992 JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
 993 {
 994     free((void *)str);
 995 }
 996 
 997 /*
 998  * Export the platform dependent path canonicalization so that
 999  * VM can find it when loading system classes.
1000  * This function is also used by the instrumentation agent.
1001  */
1002 extern int canonicalize(char *path, const char *out, int len);
1003 
1004 JNIEXPORT int
1005 Canonicalize(JNIEnv *unused, char *orig, char *out, int len)
1006 {
1007     /* canonicalize an already natived path */
1008     return canonicalize(orig, out, len);
1009 }
1010 


< prev index next >